diff --git a/.hgtags b/.hgtags index c8669af3d81..1ee273ac14c 100644 --- a/.hgtags +++ b/.hgtags @@ -382,3 +382,5 @@ e384420383a5b79fa0012ebcb25d8f83cff7f777 jdk-9+135 9cb87c88ed851c0575b8ead753ea238ed5b544e9 jdk-9+137 d273dfe9a126d3bffe92072547fef2cd1361b0eb jdk-9+138 65477538bec32963dc41153d89c4417eb46c45fc jdk-9+139 +0875007901f7d364a08220b052f0c81003e9c8c5 jdk-9+140 +9aadd2163b568d76f8969ad2fb404a63733da359 jdk-9+141 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index ec2e8625423..c325445921e 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -382,3 +382,5 @@ be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133 d7f519b004254b19e384131d9f0d0e40e31a0fd3 jdk-9+137 67c4388142bdf58aec8fefa4475faaa8a5d7380c jdk-9+138 7dcf453eacae79ee86a6bcc75fd0b546fc99b48a jdk-9+139 +a5815c6098a241d3a1df64d22b84b3524e4a77df jdk-9+140 +f64afae7f1a5608e438585bbf0bc23785e69cba0 jdk-9+141 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 8404ca42d02..7f8c42f6b98 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -428,9 +428,10 @@ AC_DEFUN([BASIC_SETUP_TOOL], # Call BASIC_SETUP_TOOL with AC_PATH_PROGS to locate the tool # $1: variable to set # $2: executable name (or list of names) to look for +# $3: [path] AC_DEFUN([BASIC_PATH_PROGS], [ - BASIC_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2)]) + BASIC_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2, , $3)]) ]) # Call BASIC_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool @@ -444,9 +445,10 @@ AC_DEFUN([BASIC_CHECK_TOOLS], # Like BASIC_PATH_PROGS but fails if no tool was found. # $1: variable to set # $2: executable name (or list of names) to look for +# $3: [path] AC_DEFUN([BASIC_REQUIRE_PROGS], [ - BASIC_PATH_PROGS($1, $2) + BASIC_PATH_PROGS($1, $2, , $3) BASIC_CHECK_NONEMPTY($1) ]) @@ -1065,7 +1067,9 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], BASIC_PATH_PROGS(HG, hg) BASIC_PATH_PROGS(STAT, stat) BASIC_PATH_PROGS(TIME, time) - BASIC_PATH_PROGS(DTRACE, dtrace) + # Dtrace is usually found in /usr/sbin on Solaris, but that directory may not + # be in the user path. + BASIC_PATH_PROGS(DTRACE, dtrace, $PATH:/usr/sbin) BASIC_PATH_PROGS(PATCH, [gpatch patch]) # Check if it's GNU time IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` diff --git a/common/autoconf/basics_windows.m4 b/common/autoconf/basics_windows.m4 index 52aea899351..1a79bf8fc86 100644 --- a/common/autoconf/basics_windows.m4 +++ b/common/autoconf/basics_windows.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4 index 83ec28e39bb..ab2bd9a87d7 100644 --- a/common/autoconf/boot-jdk.m4 +++ b/common/autoconf/boot-jdk.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/bootcycle-spec.gmk.in b/common/autoconf/bootcycle-spec.gmk.in index 3c9c1dbe23b..e26450ae3fc 100644 --- a/common/autoconf/bootcycle-spec.gmk.in +++ b/common/autoconf/bootcycle-spec.gmk.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index 6ca891c3291..863875065a6 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -168,7 +168,6 @@ AC_DEFUN([BPERF_SETUP_CCACHE], [AS_HELP_STRING([--enable-ccache], [enable using ccache to speed up recompilations @<:@disabled@:>@])]) - CCACHE= CCACHE_STATUS= AC_MSG_CHECKING([is ccache enabled]) if test "x$enable_ccache" = xyes; then diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in index a643d82e45b..dba07605a22 100644 --- a/common/autoconf/buildjdk-spec.gmk.in +++ b/common/autoconf/buildjdk-spec.gmk.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -156,7 +156,3 @@ JVM_VARIANT_KERNEL := false JVM_VARIANT_ZERO := false JVM_VARIANT_ZEROSHARK := false JVM_VARIANT_CORE := false - -# Sneak this in via the spec.gmk file, since we don't want to mess around too much with the Hotspot make files. -# This is needed to get the LOG setting to work properly. -include $(SRC_ROOT)/make/common/MakeBase.gmk diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index f7e2003ca32..44933806256 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index dbb65dfe1ec..d6a4ef04152 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -895,7 +895,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], elif test "x$OPENJDK_$1_OS" = xsolaris; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSOLARIS" $2JVM_CFLAGS="[$]$2JVM_CFLAGS -template=no%extdef -features=no%split_init \ - -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + -D_Crun_inline_placement -library=%none -KPIC -mt -features=no%except" elif test "x$OPENJDK_$1_OS" = xmacosx; then $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_ALLBSD_SOURCE" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 48b23344af8..49acd1801d7 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -3657,6 +3657,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Call BASIC_SETUP_TOOL with AC_PATH_PROGS to locate the tool # $1: variable to set # $2: executable name (or list of names) to look for +# $3: [path] # Call BASIC_SETUP_TOOL with AC_CHECK_TOOLS to locate the tool @@ -3667,6 +3668,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Like BASIC_PATH_PROGS but fails if no tool was found. # $1: variable to set # $2: executable name (or list of names) to look for +# $3: [path] # Like BASIC_SETUP_TOOL but fails if no tool was found. @@ -3733,7 +3735,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -3792,7 +3794,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # ... then the rest # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4403,7 +4405,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4498,7 +4500,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4818,7 +4820,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -5091,7 +5093,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1475218974 +DATE_WHEN_GENERATED=1477108079 ############################################################################### # @@ -22769,6 +22771,8 @@ $as_echo "$tool_specified" >&6; } fi + # Dtrace is usually found in /usr/sbin on Solaris, but that directory may not + # be in the user path. # Publish this variable in the help. @@ -22791,7 +22795,8 @@ else ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH +as_dummy="$PATH:/usr/sbin" +for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. @@ -22849,7 +22854,8 @@ else ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH +as_dummy="$PATH:/usr/sbin" +for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. @@ -50071,7 +50077,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA elif test "x$OPENJDK_TARGET_OS" = xsolaris; then JVM_CFLAGS="$JVM_CFLAGS -DSOLARIS" JVM_CFLAGS="$JVM_CFLAGS -template=no%extdef -features=no%split_init \ - -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + -D_Crun_inline_placement -library=%none -KPIC -mt -features=no%except" elif test "x$OPENJDK_TARGET_OS" = xmacosx; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" JVM_CFLAGS="$JVM_CFLAGS -D_ALLBSD_SOURCE" @@ -50886,7 +50892,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA elif test "x$OPENJDK_BUILD_OS" = xsolaris; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSOLARIS" OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -template=no%extdef -features=no%split_init \ - -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + -D_Crun_inline_placement -library=%none -KPIC -mt -features=no%except" elif test "x$OPENJDK_BUILD_OS" = xmacosx; then OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_ALLBSD_SOURCE" @@ -65239,7 +65245,6 @@ if test "${enable_ccache+set}" = set; then : fi - CCACHE= CCACHE_STATUS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking is ccache enabled" >&5 $as_echo_n "checking is ccache enabled... " >&6; } diff --git a/common/autoconf/jdk-version.m4 b/common/autoconf/jdk-version.m4 index 3b2fbfb60f1..4846c12647c 100644 --- a/common/autoconf/jdk-version.m4 +++ b/common/autoconf/jdk-version.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/lib-bundled.m4 b/common/autoconf/lib-bundled.m4 index 9c8ad722fd8..218d3f87adf 100644 --- a/common/autoconf/lib-bundled.m4 +++ b/common/autoconf/lib-bundled.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/source-dirs.m4 b/common/autoconf/source-dirs.m4 index fa2f74d2237..940707e81a0 100644 --- a/common/autoconf/source-dirs.m4 +++ b/common/autoconf/source-dirs.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 710cf70ab7c..7725e6fe84c 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -175,7 +175,7 @@ VERSION_NUMBER_FOUR_POSITIONS := @VERSION_NUMBER_FOUR_POSITIONS@ VERSION_STRING := @VERSION_STRING@ # The short version string, without trailing zeroes and just PRE, if present. VERSION_SHORT := @VERSION_SHORT@ -# The Java specification version. It usually equals to the major version number. +# The Java specification version. It usually equals the major version number. VERSION_SPECIFICATION := @VERSION_MAJOR@ # A GA version is defined by the PRE string being empty. Rather than testing for # that, this variable defines it with true/false. @@ -244,9 +244,6 @@ USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@ # Only build headless support or not ENABLE_HEADLESS_ONLY := @ENABLE_HEADLESS_ONLY@ -# Legacy support -USE_NEW_HOTSPOT_BUILD:=@USE_NEW_HOTSPOT_BUILD@ - # JDK_OUTPUTDIR specifies where a working jvm is built. # You can run $(JDK_OUTPUTDIR)/bin/java # Though the layout of the contents of $(JDK_OUTPUTDIR) is not diff --git a/common/autoconf/version-numbers b/common/autoconf/version-numbers index 98f106680b5..ac2c9f24655 100644 --- a/common/autoconf/version-numbers +++ b/common/autoconf/version-numbers @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index 7b76ab37029..a4c4278299a 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh index 7320aa09a11..3007d3e8860 100644 --- a/common/bin/hgforest.sh +++ b/common/bin/hgforest.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/bin/jib.sh b/common/bin/jib.sh index ea52385537b..ceac118bb77 100644 --- a/common/bin/jib.sh +++ b/common/bin/jib.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index d003e1815e4..fa3c5749f8c 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,7 +287,8 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system", + "--enable-dtrace"), default_make_targets: common.default_make_targets }, @@ -295,7 +296,8 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "sparcv9", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system", + "--enable-dtrace"), default_make_targets: common.default_make_targets }, diff --git a/corba/.hgtags b/corba/.hgtags index c5bbcbce5a7..49efbd70a16 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -382,3 +382,5 @@ aa053a3faf266c12b4fd5272da431a3e08e4a3e3 jdk-9+136 258cf18fa7fc59359b874f8743b7168dc48baf73 jdk-9+137 27bb44be32076861a0951bcefb07a1d92509a4b6 jdk-9+138 8c9da7fc5b07c606afd571c7012441b77dda83b2 jdk-9+139 +9f3fc931bc230f44f2a58d75f7f6360af98bb113 jdk-9+140 +b32f998da32b488ec7c4e9dbb3c750841b48e74d jdk-9+141 diff --git a/corba/make/gensrc/Gensrc-java.corba.gmk b/corba/make/gensrc/Gensrc-java.corba.gmk index f7f9b4ee53c..4899790c67f 100644 --- a/corba/make/gensrc/Gensrc-java.corba.gmk +++ b/corba/make/gensrc/Gensrc-java.corba.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java index a23eec3c4c1..8993aa51e91 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java @@ -31,22 +31,17 @@ package com.sun.corba.se.impl.io; -import java.io.InputStream; import java.io.IOException; import java.io.StreamCorruptedException; import java.io.ObjectInputValidation; import java.io.NotActiveException; import java.io.InvalidObjectException; import java.io.InvalidClassException; -import java.io.DataInputStream; import java.io.OptionalDataException; -import java.io.WriteAbortedException; import java.io.Externalizable; import java.io.EOFException; import java.lang.reflect.*; import java.util.Vector; -import java.util.Stack; -import java.util.Hashtable; import java.util.Enumeration; import sun.corba.Bridge ; @@ -54,7 +49,6 @@ import sun.corba.Bridge ; import java.security.AccessController ; import java.security.PrivilegedAction ; -import com.sun.corba.se.impl.io.ObjectStreamClass; import com.sun.corba.se.impl.util.Utility; import org.omg.CORBA.portable.ValueInputStream; @@ -71,14 +65,12 @@ import org.omg.CORBA.TypeCode; import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription; import com.sun.org.omg.SendingContext.CodeBase; -import javax.rmi.PortableRemoteObject; import javax.rmi.CORBA.Util; import javax.rmi.CORBA.ValueHandler; import java.security.*; import java.util.*; -import com.sun.corba.se.impl.orbutil.ObjectUtility ; import com.sun.corba.se.impl.logging.OMGSystemException ; import com.sun.corba.se.impl.logging.UtilSystemException ; @@ -182,75 +174,6 @@ public class IIOPInputStream private byte streamFormatVersion; - // Since java.io.OptionalDataException's constructors are - // package private, but we need to throw it in some special - // cases, we try to do it by reflection. - private static final Constructor OPT_DATA_EXCEPTION_CTOR; - - private Object[] readObjectArgList = { this } ; - - static { - OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor(); - } - - // Grab the OptionalDataException boolean ctor and make - // it accessible. Note that any exceptions - // will be wrapped in ExceptionInInitializerErrors. - private static Constructor getOptDataExceptionCtor() { - - try { - - Constructor result = - - (Constructor) AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public java.lang.Object run() - throws NoSuchMethodException, - SecurityException { - - Constructor boolCtor - = OptionalDataException.class.getDeclaredConstructor( - new Class[] { - Boolean.TYPE }); - - boolCtor.setAccessible(true); - - return boolCtor; - }}); - - if (result == null) - // XXX I18N, logging needed. - throw new Error("Unable to find OptionalDataException constructor"); - - return result; - - } catch (Exception ex) { - // XXX I18N, logging needed. - throw new ExceptionInInitializerError(ex); - } - } - - // Create a new OptionalDataException with the EOF marker - // set to true. See handleOptionalDataMarshalException. - private OptionalDataException createOptionalDataException() { - try { - OptionalDataException result - = (OptionalDataException) - OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] { - Boolean.TRUE }); - - if (result == null) - // XXX I18N, logging needed. - throw new Error("Created null OptionalDataException"); - - return result; - - } catch (Exception ex) { - // XXX I18N, logging needed. - throw new Error("Couldn't create OptionalDataException", ex); - } - } - // Return the stream format version currently being used // to deserialize an object protected byte getStreamFormatVersion() { @@ -395,7 +318,6 @@ public class IIOPInputStream int offset) /* throws OptionalDataException, ClassNotFoundException, IOException */ { - /* Save the current state and get ready to read an object. */ Object prevObject = currentObject; ObjectStreamClass prevClassDesc = currentClassDesc; @@ -947,7 +869,7 @@ public class IIOPInputStream if (!objectRead) result = new EOFException("No more optional data"); else - result = createOptionalDataException(); + result = bridge.newOptionalDataExceptionForSerialization(true); result.initCause(marshalException); @@ -1230,8 +1152,7 @@ public class IIOPInputStream readObjectState.beginUnmarshalCustomValue(this, calledDefaultWriteObject, - (currentClassDesc.readObjectMethod - != null)); + currentClassDesc.hasReadObject()); } else { if (currentClassDesc.hasReadObject()) setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); @@ -1556,8 +1477,7 @@ public class IIOPInputStream readObjectState.beginUnmarshalCustomValue(this, calledDefaultWriteObject, - (currentClassDesc.readObjectMethod - != null)); + currentClassDesc.hasReadObject()); } boolean usedReadObject = false; @@ -1714,13 +1634,8 @@ public class IIOPInputStream throws InvalidClassException, StreamCorruptedException, ClassNotFoundException, IOException { - if (osc.readObjectMethod == null) { - return false; - } - try { - osc.readObjectMethod.invoke( obj, readObjectArgList ) ; - return true; + return osc.invokeReadObject( obj, this ) ; } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof ClassNotFoundException) @@ -1734,8 +1649,6 @@ public class IIOPInputStream else // XXX I18N, logging needed. throw new Error("internal error"); - } catch (IllegalAccessException e) { - return false; } } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java index a8fcb186c8b..e5f77093aae 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java @@ -31,33 +31,23 @@ package com.sun.corba.se.impl.io; -import org.omg.CORBA.INTERNAL; import org.omg.CORBA.portable.OutputStream; import java.security.AccessController ; import java.security.PrivilegedAction ; import java.io.IOException; -import java.io.DataOutputStream; -import java.io.Serializable; import java.io.InvalidClassException; -import java.io.StreamCorruptedException; import java.io.Externalizable; -import java.io.ObjectStreamException; import java.io.NotSerializableException; import java.io.NotActiveException; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Field; - -import java.util.Stack; import javax.rmi.CORBA.Util; -import javax.rmi.CORBA.ValueHandlerMultiFormat; import sun.corba.Bridge ; -import com.sun.corba.se.impl.io.ObjectStreamClass; import com.sun.corba.se.impl.util.Utility; import com.sun.corba.se.impl.util.RepositoryId; @@ -621,7 +611,7 @@ public class IIOPOutputStream writeObjectState.enterWriteObject(this); // writeObject(obj, c, this); - osc.writeObjectMethod.invoke( obj, writeObjectArgList ) ; + osc.invokeWriteObject( obj, this ) ; writeObjectState.exitWriteObject(this); @@ -636,8 +626,6 @@ public class IIOPOutputStream else // XXX I18N, Logging needed. throw new Error("invokeObjectWriter internal error",e); - } catch (IllegalAccessException e) { - // cannot happen } } @@ -761,59 +749,52 @@ public class IIOPOutputStream */ private void outputClassFields(Object o, Class cl, ObjectStreamField[] fields) - throws IOException, InvalidClassException { + throws IOException { for (int i = 0; i < fields.length; i++) { if (fields[i].getField() == null) - // XXX I18N, Logging needed. throw new InvalidClassException(cl.getName(), "Nonexistent field " + fields[i].getName()); - - try { - switch (fields[i].getTypeCode()) { - case 'B': - byte byteValue = fields[i].getField().getByte( o ) ; - orbStream.write_octet(byteValue); - break; - case 'C': - char charValue = fields[i].getField().getChar( o ) ; - orbStream.write_wchar(charValue); - break; - case 'F': - float floatValue = fields[i].getField().getFloat( o ) ; - orbStream.write_float(floatValue); - break; - case 'D' : - double doubleValue = fields[i].getField().getDouble( o ) ; - orbStream.write_double(doubleValue); - break; - case 'I': - int intValue = fields[i].getField().getInt( o ) ; - orbStream.write_long(intValue); - break; - case 'J': - long longValue = fields[i].getField().getLong( o ) ; - orbStream.write_longlong(longValue); - break; - case 'S': - short shortValue = fields[i].getField().getShort( o ) ; - orbStream.write_short(shortValue); - break; - case 'Z': - boolean booleanValue = fields[i].getField().getBoolean( o ) ; - orbStream.write_boolean(booleanValue); - break; - case '[': - case 'L': - Object objectValue = fields[i].getField().get( o ) ; - writeObjectField(fields[i], objectValue); - break; - default: - // XXX I18N, Logging needed. - throw new InvalidClassException(cl.getName()); - } - } catch (IllegalAccessException exc) { - throw wrapper.illegalFieldAccess( exc, fields[i].getName() ) ; + switch (fields[i].getTypeCode()) { + case 'B': + byte byteValue = bridge.getByte(o, fields[i].getFieldID()) ; + orbStream.write_octet(byteValue); + break; + case 'C': + char charValue = bridge.getChar(o, fields[i].getFieldID()) ; + orbStream.write_wchar(charValue); + break; + case 'F': + float floatValue = bridge.getFloat(o, fields[i].getFieldID()) ; + orbStream.write_float(floatValue); + break; + case 'D' : + double doubleValue = bridge.getDouble(o, fields[i].getFieldID()) ; + orbStream.write_double(doubleValue); + break; + case 'I': + int intValue = bridge.getInt(o, fields[i].getFieldID()) ; + orbStream.write_long(intValue); + break; + case 'J': + long longValue = bridge.getLong(o, fields[i].getFieldID()) ; + orbStream.write_longlong(longValue); + break; + case 'S': + short shortValue = bridge.getShort(o, fields[i].getFieldID()) ; + orbStream.write_short(shortValue); + break; + case 'Z': + boolean booleanValue = bridge.getBoolean(o, fields[i].getFieldID()) ; + orbStream.write_boolean(booleanValue); + break; + case '[': + case 'L': + Object objectValue = bridge.getObject(o, fields[i].getFieldID()) ; + writeObjectField(fields[i], objectValue); + break; + default: + throw new InvalidClassException(cl.getName()); } } } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java index 5e6bba759e3..b875d25cb32 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java @@ -31,16 +31,16 @@ package com.sun.corba.se.impl.io; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.invoke.MethodHandle; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.DigestOutputStream; import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; import java.security.PrivilegedAction; import java.lang.reflect.Modifier; -import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; @@ -80,9 +80,6 @@ public class ObjectStreamClass implements java.io.Serializable { public static final long kDefaultUID = -1; - private static Object noArgsList[] = {}; - private static Class noTypesList[] = {}; - /** true if represents enum type */ private boolean isEnum; @@ -311,12 +308,37 @@ public class ObjectStreamClass implements java.io.Serializable { return null; } + public final boolean invokeWriteObject(Object obj, ObjectOutputStream ois) throws InvocationTargetException { + if (!hasWriteObject()) { + return false; + } + try { + writeObjectMethod.invoke(obj, ois); + } catch (Throwable t) { + throw new InvocationTargetException(t, "writeObject"); + } + return true; + } + + public final boolean invokeReadObject(Object obj, ObjectInputStream ois) throws InvocationTargetException { + if (hasReadObject()) { + try { + readObjectMethod.invoke(obj, ois); + return true; + } catch (Throwable t) { + throw new InvocationTargetException(t, "readObject"); + } + } else { + return false; + } + } + public Serializable writeReplace(Serializable value) { if (writeReplaceObjectMethod != null) { try { - return (Serializable) writeReplaceObjectMethod.invoke(value,noArgsList); - } catch(Throwable t) { - throw new RuntimeException(t); + return (Serializable) writeReplaceObjectMethod.invoke(value); + } catch (Throwable t) { + throw new InternalError("unexpected error", t); } } else return value; @@ -325,9 +347,9 @@ public class ObjectStreamClass implements java.io.Serializable { public Object readResolve(Object value) { if (readResolveObjectMethod != null) { try { - return readResolveObjectMethod.invoke(value,noArgsList); - } catch(Throwable t) { - throw new RuntimeException(t); + return readResolveObjectMethod.invoke(value); + } catch (Throwable t) { + throw new InternalError("unexpected error", t); } } else return value; @@ -382,31 +404,34 @@ public class ObjectStreamClass implements java.io.Serializable { */ } - private static final class PersistentFieldsValue + static final class PersistentFieldsValue extends ClassValue { PersistentFieldsValue() { } protected ObjectStreamField[] computeValue(Class type) { try { + bridge.ensureClassInitialized(type); Field pf = type.getDeclaredField("serialPersistentFields"); int mods = pf.getModifiers(); if (Modifier.isPrivate(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { - pf.setAccessible(true); + long offset = bridge.staticFieldOffset(pf); java.io.ObjectStreamField[] fields = - (java.io.ObjectStreamField[])pf.get(type); + (java.io.ObjectStreamField[])bridge.getObject(type, offset); return translateFields(fields); } - } catch (NoSuchFieldException | IllegalAccessException | + } catch (NoSuchFieldException | IllegalArgumentException | ClassCastException e) { } return null; } - private static ObjectStreamField[] translateFields( - java.io.ObjectStreamField[] fields) { + private static ObjectStreamField[] translateFields(java.io.ObjectStreamField[] fields) { + if (fields == null) { + return null; + } ObjectStreamField[] translation = - new ObjectStreamField[fields.length]; + new ObjectStreamField[fields.length]; for (int i = 0; i < fields.length; i++) { translation[i] = new ObjectStreamField(fields[i].getName(), fields[i].getType()); @@ -450,13 +475,11 @@ public class ObjectStreamClass implements java.io.Serializable { * If it is declared, use the declared serialPersistentFields. * Otherwise, extract the fields from the class itself. */ - fields = persistentFieldsValue.get(cl); + fields = persistentFieldsValue.get(cl); if (fields == null) { - /* Get all of the declared fields for this - * Class. setAccessible on all fields so they - * can be accessed later. Create a temporary - * ObjectStreamField array to hold each + /* Get all of the declared fields for this Class. + * Create a temporary ObjectStreamField array to hold each * non-static, non-transient field. Then copy the * temporary array into an array of the correct * size once the number of fields is known. @@ -471,7 +494,6 @@ public class ObjectStreamClass implements java.io.Serializable { int modifiers = fld.getModifiers(); if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) { - fld.setAccessible(true) ; tempFields[numFields++] = new ObjectStreamField(fld); } } @@ -487,7 +509,6 @@ public class ObjectStreamClass implements java.io.Serializable { try { Field reflField = cl.getDeclaredField(fields[j].getName()); if (fields[j].getType() == reflField.getType()) { - reflField.setAccessible(true); fields[j].setField(reflField); } } catch (NoSuchFieldException e) { @@ -527,8 +548,8 @@ public class ObjectStreamClass implements java.io.Serializable { int mods = f.getModifiers(); // SerialBug 5: static final SUID should be read if (Modifier.isStatic(mods) && Modifier.isFinal(mods) ) { - f.setAccessible(true); - suid = f.getLong(cl); + long offset = bridge.staticFieldOffset(f); + suid = bridge.getLong(cl, offset); // SerialBug 2: should be computed after writeObject // actualSuid = computeStructuralUID(cl); } else { @@ -540,16 +561,12 @@ public class ObjectStreamClass implements java.io.Serializable { suid = _computeSerialVersionUID(cl); // SerialBug 2: should be computed after writeObject // actualSuid = computeStructuralUID(cl); - } catch (IllegalAccessException ex) { - suid = _computeSerialVersionUID(cl); } } - writeReplaceObjectMethod = ObjectStreamClass.getInheritableMethod(cl, - "writeReplace", noTypesList, Object.class); + writeReplaceObjectMethod = bridge.writeReplaceForSerialization(cl); - readResolveObjectMethod = ObjectStreamClass.getInheritableMethod(cl, - "readResolve", noTypesList, Object.class); + readResolveObjectMethod = bridge.readResolveForSerialization(cl); if (externalizable) cons = getExternalizableConstructor(cl) ; @@ -557,14 +574,8 @@ public class ObjectStreamClass implements java.io.Serializable { cons = getSerializableConstructor(cl) ; if (serializable && !forProxyClass) { - /* Look for the writeObject method - * Set the accessible flag on it here. ObjectOutputStream - * will call it as necessary. - */ - writeObjectMethod = getPrivateMethod( cl, "writeObject", - new Class[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ; - readObjectMethod = getPrivateMethod( cl, "readObject", - new Class[] { java.io.ObjectInputStream.class }, Void.TYPE ) ; + writeObjectMethod = bridge.writeObjectForSerialization(cl) ; + readObjectMethod = bridge.readObjectForSerialization(cl); } return null; } @@ -585,27 +596,6 @@ public class ObjectStreamClass implements java.io.Serializable { } } - /** - * Returns non-static private method with given signature defined by given - * class, or null if none found. Access checks are disabled on the - * returned method (if any). - */ - private static Method getPrivateMethod(Class cl, String name, - Class[] argTypes, - Class returnType) - { - try { - Method meth = cl.getDeclaredMethod(name, argTypes); - meth.setAccessible(true); - int mods = meth.getModifiers(); - return ((meth.getReturnType() == returnType) && - ((mods & Modifier.STATIC) == 0) && - ((mods & Modifier.PRIVATE) != 0)) ? meth : null; - } catch (NoSuchMethodException ex) { - return null; - } - } - // Specific to RMI-IIOP /** * Java to IDL ptc-02-01-12 1.5.1 @@ -848,6 +838,22 @@ public class ObjectStreamClass implements java.io.Serializable { return writeObjectMethod != null ; } + /** + * Returns true if represented class is serializable or externalizable and + * defines a conformant writeReplace method. Otherwise, returns false. + */ + boolean hasWriteReplaceMethod() { + return (writeReplaceObjectMethod != null); + } + + /** + * Returns true if represented class is serializable or externalizable and + * defines a conformant readResolve method. Otherwise, returns false. + */ + boolean hasReadResolveMethod() { + return (readResolveObjectMethod != null); + } + /** * Returns when or not this class should be custom * marshaled (use chunking). This should happen if @@ -904,7 +910,7 @@ public class ObjectStreamClass implements java.io.Serializable { { if (cons != null) { try { - return cons.newInstance(new Object[0]); + return cons.newInstance(); } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed InternalError ie = new InternalError(); @@ -912,7 +918,7 @@ public class ObjectStreamClass implements java.io.Serializable { throw ie ; } } else { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("no constructor for " + ofClass); } } @@ -921,15 +927,8 @@ public class ObjectStreamClass implements java.io.Serializable { * Access checks are disabled on the returned constructor (if any), since * the defining class may still be non-public. */ - private static Constructor getExternalizableConstructor(Class cl) { - try { - Constructor cons = cl.getDeclaredConstructor(new Class[0]); - cons.setAccessible(true); - return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ? - cons : null; - } catch (NoSuchMethodException ex) { - return null; - } + private static Constructor getExternalizableConstructor(Class cl) { + return bridge.newConstructorForExternalization(cl); } /** @@ -937,28 +936,8 @@ public class ObjectStreamClass implements java.io.Serializable { * superclass, or null if none found. Access checks are disabled on the * returned constructor (if any). */ - private static Constructor getSerializableConstructor(Class cl) { - Class initCl = cl; - while (Serializable.class.isAssignableFrom(initCl)) { - if ((initCl = initCl.getSuperclass()) == null) { - return null; - } - } - try { - Constructor cons = initCl.getDeclaredConstructor(new Class[0]); - int mods = cons.getModifiers(); - if ((mods & Modifier.PRIVATE) != 0 || - ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && - !packageEquals(cl, initCl))) - { - return null; - } - cons = bridge.newConstructorForSerialization(cl, cons); - cons.setAccessible(true); - return cons; - } catch (NoSuchMethodException ex) { - return null; - } + private static Constructor getSerializableConstructor(Class cl) { + return bridge.newConstructorForSerialization(cl); } /* @@ -1522,11 +1501,11 @@ public class ObjectStreamClass implements java.io.Serializable { * @since JDK 1.2 */ private boolean hasExternalizableBlockData; - Method writeObjectMethod; - Method readObjectMethod; - private transient Method writeReplaceObjectMethod; - private transient Method readResolveObjectMethod; - private Constructor cons ; + private transient MethodHandle writeObjectMethod; + private transient MethodHandle readObjectMethod; + private transient MethodHandle writeReplaceObjectMethod; + private transient MethodHandle readResolveObjectMethod; + private transient Constructor cons; /** * Beginning in Java to IDL ptc/02-01-12, RMI-IIOP has a @@ -1543,44 +1522,12 @@ public class ObjectStreamClass implements java.io.Serializable { */ private ObjectStreamClass localClassDesc; - /* Find out if the class has a static class initializer */ - private static Method hasStaticInitializerMethod = null; /** * Returns true if the given class defines a static initializer method, * false otherwise. */ private static boolean hasStaticInitializer(Class cl) { - if (hasStaticInitializerMethod == null) { - Class classWithThisMethod = null; - - try { - if (classWithThisMethod == null) - classWithThisMethod = java.io.ObjectStreamClass.class; - - hasStaticInitializerMethod = - classWithThisMethod.getDeclaredMethod("hasStaticInitializer", - new Class[] { Class.class }); - } catch (NoSuchMethodException ex) { - } - - if (hasStaticInitializerMethod == null) { - // XXX I18N, logging needed - throw new InternalError("Can't find hasStaticInitializer method on " - + classWithThisMethod.getName()); - } - hasStaticInitializerMethod.setAccessible(true); - } - - try { - Boolean retval = (Boolean) - hasStaticInitializerMethod.invoke(null, new Object[] { cl }); - return retval.booleanValue(); - } catch (Exception ex) { - // XXX I18N, logging needed - InternalError ie = new InternalError( "Error invoking hasStaticInitializer" ) ; - ie.initCause( ex ) ; - throw ie ; - } + return bridge.hasStaticInitializerForSerialization(cl); } @@ -1754,7 +1701,6 @@ public class ObjectStreamClass implements java.io.Serializable { if ((meth == null) || (meth.getReturnType() != returnType)) { return null; } - meth.setAccessible(true); int mods = meth.getModifiers(); if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) { return null; diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java index 8c21cc30ca0..58cff065605 100644 --- a/corba/src/java.corba/share/classes/module-info.java +++ b/corba/src/java.corba/share/classes/module-info.java @@ -32,6 +32,7 @@ module java.corba { requires java.logging; requires java.naming; requires java.transaction; + requires jdk.unsupported; exports javax.activity; exports javax.rmi; diff --git a/corba/src/java.corba/share/classes/sun/corba/Bridge.java b/corba/src/java.corba/share/classes/sun/corba/Bridge.java index ddc96b21a7c..0291df564bf 100644 --- a/corba/src/java.corba/share/classes/sun/corba/Bridge.java +++ b/corba/src/java.corba/share/classes/sun/corba/Bridge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * 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,25 +25,24 @@ package sun.corba ; +import java.io.OptionalDataException; +import java.lang.invoke.MethodHandle; import java.lang.reflect.Field ; -import java.lang.reflect.Method ; import java.lang.reflect.Constructor ; -import java.lang.reflect.InvocationTargetException ; - -import java.io.ObjectInputStream ; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; -import jdk.internal.misc.Unsafe ; -import jdk.internal.reflect.ReflectionFactory; +import sun.misc.Unsafe; +import sun.reflect.ReflectionFactory; /** This class provides the methods for fundamental JVM operations * needed in the ORB that are not part of the public Java API. This includes: * * @@ -201,10 +201,9 @@ public class CookieManager extends CookieHandler throw new IllegalArgumentException("Argument is null"); } - Map> cookieMap = new java.util.HashMap<>(); // if there's no default CookieStore, no way for us to get any cookie if (cookieJar == null) - return Collections.unmodifiableMap(cookieMap); + return Map.of(); boolean secureLink = "https".equalsIgnoreCase(uri.getScheme()); List cookies = new java.util.ArrayList<>(); @@ -244,8 +243,7 @@ public class CookieManager extends CookieHandler // apply sort rule (RFC 2965 sec. 3.3.4) List cookieHeader = sortByPath(cookies); - cookieMap.put("Cookie", cookieHeader); - return Collections.unmodifiableMap(cookieMap); + return Map.of("Cookie", cookieHeader); } public void diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index 4a59099c0e7..b008b35260a 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -321,6 +321,13 @@ class InetAddress implements java.io.Serializable { public String getOriginalHostName(InetAddress ia) { return ia.holder.getOriginalHostName(); } + + public InetAddress getByName(String hostName, + InetAddress hostAddress) + throws UnknownHostException + { + return InetAddress.getByName(hostName, hostAddress); + } } ); init(); diff --git a/jdk/src/java.base/share/classes/java/net/URI.java b/jdk/src/java.base/share/classes/java/net/URI.java index 97d8937f53d..599deff1e0c 100644 --- a/jdk/src/java.base/share/classes/java/net/URI.java +++ b/jdk/src/java.base/share/classes/java/net/URI.java @@ -37,6 +37,9 @@ import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.nio.charset.CharacterCodingException; import java.text.Normalizer; +import jdk.internal.loader.URLClassPath; +import jdk.internal.misc.JavaNetUriAccess; +import jdk.internal.misc.SharedSecrets; import sun.nio.cs.ThreadLocalCoders; import java.lang.Character; // for javadoc @@ -819,6 +822,25 @@ public final class URI .parse(false); } + /** + * Constructs a simple URI consisting of only a scheme and a pre-validated + * path. Provides a fast-path for some internal cases. + */ + URI(String scheme, String path) { + assert validSchemeAndPath(scheme, path); + this.scheme = scheme; + this.path = path; + } + + private static boolean validSchemeAndPath(String scheme, String path) { + try { + URI u = new URI(scheme + ":" + path); + return scheme.equals(u.scheme) && path.equals(u.path); + } catch (URISyntaxException e) { + return false; + } + } + /** * Creates a URI by parsing the given string. * @@ -3571,5 +3593,13 @@ public final class URI } } - + static { + SharedSecrets.setJavaNetUriAccess( + new JavaNetUriAccess() { + public URI create(String scheme, String path) { + return new URI(scheme, path); + } + } + ); + } } diff --git a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java index 0808a6e9962..ebae81ceeb0 100644 --- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java +++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ import java.util.jar.Manifest; import jdk.internal.loader.Resource; import jdk.internal.loader.URLClassPath; -import jdk.internal.misc.JavaNetAccess; +import jdk.internal.misc.JavaNetURLClassLoaderAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.perf.PerfCounter; import sun.net.www.ParseUtil; @@ -767,10 +767,11 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { } static { - SharedSecrets.setJavaNetAccess( - new JavaNetAccess() { - public URLClassPath getURLClassPath(URLClassLoader u) { - return u.ucp; + SharedSecrets.setJavaNetURLClassLoaderAccess( + new JavaNetURLClassLoaderAccess() { + @Override + public AccessControlContext getAccessControlContext(URLClassLoader u) { + return u.acc; } } ); diff --git a/jdk/src/java.base/share/classes/java/net/URLPermission.java b/jdk/src/java.base/share/classes/java/net/URLPermission.java index 0c38008cb13..e78c7aee68c 100644 --- a/jdk/src/java.base/share/classes/java/net/URLPermission.java +++ b/jdk/src/java.base/share/classes/java/net/URLPermission.java @@ -217,7 +217,7 @@ public final class URLPermission extends Permission { * where method-names is the list of methods separated by commas * and header-names is the list of permitted headers separated by commas. * There is no white space in the returned String. If header-names is empty - * then the colon separator will not be present. + * then the colon separator may not be present. */ public String getActions() { return actions; diff --git a/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java b/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java index 63b4dc767d8..c748e32571b 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java +++ b/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java @@ -31,11 +31,10 @@ import java.io.UncheckedIOException; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; -import java.util.Objects; import java.nio.file.FileTreeWalker.Event; /** - * An {@code Iterator to iterate over the nodes of a file tree. + * An {@code Iterator} to iterate over the nodes of a file tree. * *
{@code
  *     try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
@@ -62,7 +61,7 @@ class FileTreeIterator implements Iterator, Closeable {
      * @throws  SecurityException
      *          if the security manager denies access to the starting file
      * @throws  NullPointerException
-     *          if {@code start} or {@code options} is {@ocde null} or
+     *          if {@code start} or {@code options} is {@code null} or
      *          the options array contains a {@code null} element
      */
     FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
diff --git a/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java
index 13bb629807f..b7dc93ad0f5 100644
--- a/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java
+++ b/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java
@@ -171,7 +171,7 @@ class FileTreeWalker implements Closeable {
      *          if {@code options} contains an element that is not a
      *          {@code FileVisitOption}
      * @throws  NullPointerException
-     *          if {@code options} is {@ocde null} or the options
+     *          if {@code options} is {@code null} or the options
      *          array contains a {@code null} element
      */
     FileTreeWalker(Collection options, int maxDepth) {
diff --git a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java
index 65ede7a2a83..096a7b48dc1 100644
--- a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java
+++ b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java
@@ -479,6 +479,10 @@ public abstract class KeyStoreSpi {
             } else if (engineIsKeyEntry(alias)) {
                 KeyStore.PasswordProtection pp =
                         (KeyStore.PasswordProtection)protParam;
+                if (pp.getProtectionAlgorithm() != null) {
+                    throw new KeyStoreException(
+                        "unsupported password protection algorithm");
+                }
                 char[] password = pp.getPassword();
 
                 Key key = engineGetKey(alias, password);
@@ -524,6 +528,10 @@ public abstract class KeyStoreSpi {
         KeyStore.PasswordProtection pProtect = null;
         if (protParam != null) {
             pProtect = (KeyStore.PasswordProtection)protParam;
+            if (pProtect.getProtectionAlgorithm() != null) {
+                throw new KeyStoreException(
+                    "unsupported password protection algorithm");
+            }
         }
 
         // set entry
diff --git a/jdk/src/java.base/share/classes/java/security/MessageDigest.java b/jdk/src/java.base/share/classes/java/security/MessageDigest.java
index 3c08a64fbf8..b6959f5db4f 100644
--- a/jdk/src/java.base/share/classes/java/security/MessageDigest.java
+++ b/jdk/src/java.base/share/classes/java/security/MessageDigest.java
@@ -32,10 +32,13 @@ import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.io.InputStream;
 import java.io.ByteArrayInputStream;
-
+import java.security.InvalidKeyException;
 import java.nio.ByteBuffer;
 
 import sun.security.util.Debug;
+import sun.security.util.MessageDigestSpi2;
+
+import javax.crypto.SecretKey;
 
 /**
  * This MessageDigest class provides applications the functionality of a
@@ -548,7 +551,7 @@ public abstract class MessageDigest extends MessageDigestSpi {
      * and its original parent (Object).
      */
 
-    static class Delegate extends MessageDigest {
+    static class Delegate extends MessageDigest implements MessageDigestSpi2 {
 
         // The provider implementation (delegate)
         private MessageDigestSpi digestSpi;
@@ -601,6 +604,14 @@ public abstract class MessageDigest extends MessageDigestSpi {
             digestSpi.engineUpdate(input);
         }
 
+        public void engineUpdate(SecretKey key) throws InvalidKeyException {
+            if (digestSpi instanceof MessageDigestSpi2) {
+                ((MessageDigestSpi2)digestSpi).engineUpdate(key);
+            } else {
+                throw new UnsupportedOperationException
+                ("Digest does not support update of SecretKey object");
+            }
+        }
         protected byte[] engineDigest() {
             return digestSpi.engineDigest();
         }
diff --git a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java
index 0f773b5681f..1f614d250f2 100644
--- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java
@@ -89,6 +89,11 @@ public class ProtectionDomain {
                 AccessController.getContext(), context);
         }
 
+        @Override
+        public ProtectionDomain[] getProtectDomains(AccessControlContext context) {
+            return context.getContext();
+        }
+
         private static AccessControlContext getCombinedACC(
             AccessControlContext context, AccessControlContext stack) {
             AccessControlContext acc =
diff --git a/jdk/src/java.base/share/classes/java/security/Signature.java b/jdk/src/java.base/share/classes/java/security/Signature.java
index 7efa9c9a7e6..9bfe4667df6 100644
--- a/jdk/src/java.base/share/classes/java/security/Signature.java
+++ b/jdk/src/java.base/share/classes/java/security/Signature.java
@@ -37,7 +37,6 @@ import java.nio.ByteBuffer;
 import java.security.Provider.Service;
 
 import javax.crypto.Cipher;
-import javax.crypto.CipherSpi;
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.BadPaddingException;
 import javax.crypto.NoSuchPaddingException;
@@ -180,15 +179,12 @@ public abstract class Signature extends SignatureSpi {
     private static final String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
 
     // all the services we need to lookup for compatibility with Cipher
-    private static final List rsaIds = Arrays.asList(
-        new ServiceId[] {
-            new ServiceId("Signature", "NONEwithRSA"),
-            new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
-            new ServiceId("Cipher", "RSA/ECB"),
-            new ServiceId("Cipher", "RSA//PKCS1Padding"),
-            new ServiceId("Cipher", "RSA"),
-        }
-    );
+    private static final List rsaIds = List.of(
+        new ServiceId("Signature", "NONEwithRSA"),
+        new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
+        new ServiceId("Cipher", "RSA/ECB"),
+        new ServiceId("Cipher", "RSA//PKCS1Padding"),
+        new ServiceId("Cipher", "RSA"));
 
     /**
      * Returns a Signature object that implements the specified signature
diff --git a/jdk/src/java.base/share/classes/java/time/Duration.java b/jdk/src/java.base/share/classes/java/time/Duration.java
index e2c55a971ea..cacd3999a83 100644
--- a/jdk/src/java.base/share/classes/java/time/Duration.java
+++ b/jdk/src/java.base/share/classes/java/time/Duration.java
@@ -88,8 +88,6 @@ import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAmount;
 import java.time.temporal.TemporalUnit;
 import java.time.temporal.UnsupportedTemporalTypeException;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.regex.Matcher;
@@ -578,8 +576,7 @@ public final class Duration
      * the simple initialization in Duration.
      */
     private static class DurationUnits {
-        static final List UNITS =
-                Collections.unmodifiableList(Arrays.asList(SECONDS, NANOS));
+        static final List UNITS = List.of(SECONDS, NANOS);
     }
 
     //-----------------------------------------------------------------------
diff --git a/jdk/src/java.base/share/classes/java/time/Instant.java b/jdk/src/java.base/share/classes/java/time/Instant.java
index 3fd40d04d9c..6e0dba1d506 100644
--- a/jdk/src/java.base/share/classes/java/time/Instant.java
+++ b/jdk/src/java.base/share/classes/java/time/Instant.java
@@ -610,7 +610,7 @@ public final class Instant
      * 

* The epoch second count is a simple incrementing count of seconds where * second 0 is 1970-01-01T00:00:00Z. - * The nanosecond part of the day is returned by {@code getNanosOfSecond}. + * The nanosecond part of the day is returned by {@link #getNano}. * * @return the seconds from the epoch of 1970-01-01T00:00:00Z */ @@ -623,7 +623,7 @@ public final class Instant * of the second. *

* The nanosecond-of-second value measures the total number of nanoseconds from - * the second returned by {@code getEpochSecond}. + * the second returned by {@link #getEpochSecond}. * * @return the nanoseconds within the second, always positive, never exceeds 999,999,999 */ diff --git a/jdk/src/java.base/share/classes/java/time/Period.java b/jdk/src/java.base/share/classes/java/time/Period.java index c7c04435262..e93d8a35d99 100644 --- a/jdk/src/java.base/share/classes/java/time/Period.java +++ b/jdk/src/java.base/share/classes/java/time/Period.java @@ -83,8 +83,6 @@ import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalQueries; import java.time.temporal.TemporalUnit; import java.time.temporal.UnsupportedTemporalTypeException; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; @@ -152,8 +150,7 @@ public final class Period /** * The set of supported units. */ - private static final List SUPPORTED_UNITS = - Collections.unmodifiableList(Arrays.asList(YEARS, MONTHS, DAYS)); + private static final List SUPPORTED_UNITS = List.of(YEARS, MONTHS, DAYS); /** * The number of years. diff --git a/jdk/src/java.base/share/classes/java/time/ZoneId.java b/jdk/src/java.base/share/classes/java/time/ZoneId.java index bae99f601cc..5087888da4f 100644 --- a/jdk/src/java.base/share/classes/java/time/ZoneId.java +++ b/jdk/src/java.base/share/classes/java/time/ZoneId.java @@ -76,14 +76,14 @@ import java.time.temporal.UnsupportedTemporalTypeException; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesException; import java.time.zone.ZoneRulesProvider; -import java.util.Collections; -import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.TimeZone; +import static java.util.Map.entry; + /** * A time-zone ID, such as {@code Europe/Paris}. *

@@ -220,39 +220,36 @@ public abstract class ZoneId implements Serializable { * * The map is unmodifiable. */ - public static final Map SHORT_IDS; - static { - Map map = new HashMap<>(64); - map.put("ACT", "Australia/Darwin"); - map.put("AET", "Australia/Sydney"); - map.put("AGT", "America/Argentina/Buenos_Aires"); - map.put("ART", "Africa/Cairo"); - map.put("AST", "America/Anchorage"); - map.put("BET", "America/Sao_Paulo"); - map.put("BST", "Asia/Dhaka"); - map.put("CAT", "Africa/Harare"); - map.put("CNT", "America/St_Johns"); - map.put("CST", "America/Chicago"); - map.put("CTT", "Asia/Shanghai"); - map.put("EAT", "Africa/Addis_Ababa"); - map.put("ECT", "Europe/Paris"); - map.put("IET", "America/Indiana/Indianapolis"); - map.put("IST", "Asia/Kolkata"); - map.put("JST", "Asia/Tokyo"); - map.put("MIT", "Pacific/Apia"); - map.put("NET", "Asia/Yerevan"); - map.put("NST", "Pacific/Auckland"); - map.put("PLT", "Asia/Karachi"); - map.put("PNT", "America/Phoenix"); - map.put("PRT", "America/Puerto_Rico"); - map.put("PST", "America/Los_Angeles"); - map.put("SST", "Pacific/Guadalcanal"); - map.put("VST", "Asia/Ho_Chi_Minh"); - map.put("EST", "-05:00"); - map.put("MST", "-07:00"); - map.put("HST", "-10:00"); - SHORT_IDS = Collections.unmodifiableMap(map); - } + public static final Map SHORT_IDS = Map.ofEntries( + entry("ACT", "Australia/Darwin"), + entry("AET", "Australia/Sydney"), + entry("AGT", "America/Argentina/Buenos_Aires"), + entry("ART", "Africa/Cairo"), + entry("AST", "America/Anchorage"), + entry("BET", "America/Sao_Paulo"), + entry("BST", "Asia/Dhaka"), + entry("CAT", "Africa/Harare"), + entry("CNT", "America/St_Johns"), + entry("CST", "America/Chicago"), + entry("CTT", "Asia/Shanghai"), + entry("EAT", "Africa/Addis_Ababa"), + entry("ECT", "Europe/Paris"), + entry("IET", "America/Indiana/Indianapolis"), + entry("IST", "Asia/Kolkata"), + entry("JST", "Asia/Tokyo"), + entry("MIT", "Pacific/Apia"), + entry("NET", "Asia/Yerevan"), + entry("NST", "Pacific/Auckland"), + entry("PLT", "Asia/Karachi"), + entry("PNT", "America/Phoenix"), + entry("PRT", "America/Puerto_Rico"), + entry("PST", "America/Los_Angeles"), + entry("SST", "Pacific/Guadalcanal"), + entry("VST", "Asia/Ho_Chi_Minh"), + entry("EST", "-05:00"), + entry("MST", "-07:00"), + entry("HST", "-10:00") + ); /** * Serialization version. */ diff --git a/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java b/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java index 911144d5b04..646af14d05a 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java @@ -77,8 +77,6 @@ import java.time.temporal.TemporalQueries; import java.time.temporal.TemporalUnit; import java.time.temporal.UnsupportedTemporalTypeException; import java.time.temporal.ValueRange; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -105,8 +103,7 @@ final class ChronoPeriodImpl /** * The set of supported units. */ - private static final List SUPPORTED_UNITS = - Collections.unmodifiableList(Arrays.asList(YEARS, MONTHS, DAYS)); + private static final List SUPPORTED_UNITS = List.of(YEARS, MONTHS, DAYS); /** * The chronology. diff --git a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java index ebe4e8a29d4..d61c2333303 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java @@ -59,10 +59,7 @@ package java.time.chrono; import static java.time.temporal.ChronoField.EPOCH_DAY; -import java.io.File; -import java.io.FileInputStream; import java.io.FilePermission; -import java.io.IOException; import java.io.InputStream; import java.io.InvalidObjectException; import java.io.ObjectInputStream; @@ -83,7 +80,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Properties; import sun.util.logging.PlatformLogger; @@ -512,7 +508,7 @@ public final class HijrahChronology extends AbstractChronology implements Serial @Override public List eras() { - return Arrays.asList(HijrahEra.values()); + return List.of(HijrahEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java b/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java index 60d0529f791..8e34703e4b0 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java @@ -368,7 +368,7 @@ public final class HijrahDate if (field instanceof ChronoField) { switch ((ChronoField) field) { case DAY_OF_WEEK: return getDayOfWeek(); - case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((getDayOfWeek() - 1) % 7) + 1; + case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((dayOfMonth - 1) % 7) + 1; case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1; case DAY_OF_MONTH: return this.dayOfMonth; case DAY_OF_YEAR: return this.getDayOfYear(); diff --git a/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java index 7ce8e4ba21a..4919b3d7d3a 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java @@ -90,7 +90,6 @@ import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.ValueRange; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; @@ -492,7 +491,7 @@ public final class IsoChronology extends AbstractChronology implements Serializa @Override public List eras() { - return Arrays.asList(IsoEra.values()); + return List.of(IsoEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java index 2bd38c8d755..4478c4c7de1 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java @@ -81,7 +81,6 @@ import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalField; import java.time.temporal.UnsupportedTemporalTypeException; import java.time.temporal.ValueRange; -import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.Locale; @@ -379,7 +378,7 @@ public final class JapaneseChronology extends AbstractChronology implements Seri @Override public List eras() { - return Arrays.asList(JapaneseEra.values()); + return List.of(JapaneseEra.values()); } JapaneseEra getCurrentEra() { diff --git a/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java index 8159adc0ac5..fd6fdc3e8cd 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java @@ -72,7 +72,6 @@ import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.ValueRange; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; @@ -306,7 +305,7 @@ public final class MinguoChronology extends AbstractChronology implements Serial @Override public List eras() { - return Arrays.asList(MinguoEra.values()); + return List.of(MinguoEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java index 6412c9dab15..c6938b2c530 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java @@ -342,7 +342,7 @@ public final class ThaiBuddhistChronology extends AbstractChronology implements @Override public List eras() { - return Arrays.asList(ThaiBuddhistEra.values()); + return List.of(ThaiBuddhistEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index ec5fd9c8086..a3f903a7d9a 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -1685,6 +1685,7 @@ public final class DateTimeFormatter { public DateTimeFormatter withResolverFields(TemporalField... resolverFields) { Set fields = null; if (resolverFields != null) { + // Set.of cannot be used because it is hostile to nulls and duplicate elements fields = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(resolverFields))); } if (Objects.equals(this.resolverFields, fields)) { diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java index 4e1bd4a811f..c2b8a411524 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -349,25 +349,40 @@ class DateTimeTextProvider { if (field == MONTH_OF_YEAR) { for (TextStyle textStyle : TextStyle.values()) { - Map displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( - "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale); Map map = new HashMap<>(); - if (displayNames != null) { - for (Entry entry : displayNames.entrySet()) { - map.put((long) (entry.getValue() + 1), entry.getKey()); - } - - } else { - // Narrow names may have duplicated names, such as "J" for January, Jun, July. - // Get names one by one in that case. + // Narrow names may have duplicated names, such as "J" for January, June, July. + // Get names one by one in that case. + if ((textStyle.equals(TextStyle.NARROW) || + textStyle.equals(TextStyle.NARROW_STANDALONE))) { for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) { String name; name = CalendarDataUtility.retrieveJavaTimeFieldValueName( - "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale); + "gregory", Calendar.MONTH, + month, textStyle.toCalendarStyle(), locale); if (name == null) { break; } - map.put((long) (month + 1), name); + map.put((month + 1L), name); + } + } else { + Map displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( + "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale); + if (displayNames != null) { + for (Entry entry : displayNames.entrySet()) { + map.put((long)(entry.getValue() + 1), entry.getKey()); + } + } else { + // Although probability is very less, but if other styles have duplicate names. + // Get names one by one in that case. + for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) { + String name; + name = CalendarDataUtility.retrieveJavaTimeFieldValueName( + "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale); + if (name == null) { + break; + } + map.put((month + 1L), name); + } } } if (!map.isEmpty()) { @@ -379,26 +394,41 @@ class DateTimeTextProvider { if (field == DAY_OF_WEEK) { for (TextStyle textStyle : TextStyle.values()) { - Map displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( - "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale); Map map = new HashMap<>(); - if (displayNames != null) { - for (Entry entry : displayNames.entrySet()) { - map.put((long)toWeekDay(entry.getValue()), entry.getKey()); - } - - } else { - // Narrow names may have duplicated names, such as "S" for Sunday and Saturday. - // Get names one by one in that case. + // Narrow names may have duplicated names, such as "S" for Sunday and Saturday. + // Get names one by one in that case. + if ((textStyle.equals(TextStyle.NARROW) || + textStyle.equals(TextStyle.NARROW_STANDALONE))) { for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) { String name; name = CalendarDataUtility.retrieveJavaTimeFieldValueName( - "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale); + "gregory", Calendar.DAY_OF_WEEK, + wday, textStyle.toCalendarStyle(), locale); if (name == null) { break; } map.put((long)toWeekDay(wday), name); } + } else { + Map displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( + "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale); + if (displayNames != null) { + for (Entry entry : displayNames.entrySet()) { + map.put((long)toWeekDay(entry.getValue()), entry.getKey()); + } + } else { + // Although probability is very less, but if other styles have duplicate names. + // Get names one by one in that case. + for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) { + String name; + name = CalendarDataUtility.retrieveJavaTimeFieldValueName( + "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale); + if (name == null) { + break; + } + map.put((long)toWeekDay(wday), name); + } + } } if (!map.isEmpty()) { styleMap.put(textStyle, map); diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java index c1568e46364..94264f32cce 100644 --- a/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java @@ -387,9 +387,9 @@ public final class ZoneOffsetTransition */ List getValidOffsets() { if (isGap()) { - return Collections.emptyList(); + return List.of(); } - return Arrays.asList(getOffsetBefore(), getOffsetAfter()); + return List.of(getOffsetBefore(), getOffsetAfter()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java index f6154857b8d..ed2330f38ef 100644 --- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java @@ -303,7 +303,6 @@ public final class ZoneRules implements Serializable { * Creates an instance of ZoneRules that has fixed zone rules. * * @param offset the offset this fixed zone rules is based on, not null - * @return the zone rules, not null * @see #isFixedOffset() */ private ZoneRules(ZoneOffset offset) { @@ -970,7 +969,7 @@ public final class ZoneRules implements Serializable { * @return an immutable list of transition rules, not null */ public List getTransitionRules() { - return Collections.unmodifiableList(Arrays.asList(lastRules)); + return List.of(lastRules); } /** diff --git a/jdk/src/java.base/share/classes/java/util/Date.java b/jdk/src/java.base/share/classes/java/util/Date.java index 017ea0fef01..bb9494766bd 100644 --- a/jdk/src/java.base/share/classes/java/util/Date.java +++ b/jdk/src/java.base/share/classes/java/util/Date.java @@ -85,12 +85,12 @@ import sun.util.calendar.ZoneInfo; * further information is the U.S. Naval Observatory, particularly * the Directorate of Time at: *

- *     http://tycho.usno.navy.mil
+ *     http://www.usno.navy.mil
  * 
*

* and their definitions of "Systems of Time" at: *

- *     http://tycho.usno.navy.mil/systime.html
+ *     http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time
  * 
*

* In all methods of class {@code Date} that accept or return diff --git a/jdk/src/java.base/share/classes/java/util/Optional.java b/jdk/src/java.base/share/classes/java/util/Optional.java index 514632b5ccc..28700a836f2 100644 --- a/jdk/src/java.base/share/classes/java/util/Optional.java +++ b/jdk/src/java.base/share/classes/java/util/Optional.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,7 +236,7 @@ public final class Optional { * present, otherwise an empty {@code Optional} * @throws NullPointerException if the mapping function is {@code null} */ - public Optional map(Function mapper) { + public Optional map(Function mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { return empty(); @@ -264,12 +264,14 @@ public final class Optional { * @throws NullPointerException if the mapping function is {@code null} or * returns a {@code null} result */ - public Optional flatMap(Function> mapper) { + public Optional flatMap(Function> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { return empty(); } else { - return Objects.requireNonNull(mapper.apply(value)); + @SuppressWarnings("unchecked") + Optional r = (Optional) mapper.apply(value); + return Objects.requireNonNull(r); } } @@ -286,12 +288,14 @@ public final class Optional { * produces a {@code null} result * @since 9 */ - public Optional or(Supplier> supplier) { + public Optional or(Supplier> supplier) { Objects.requireNonNull(supplier); if (isPresent()) { return this; } else { - return Objects.requireNonNull(supplier.get()); + @SuppressWarnings("unchecked") + Optional r = (Optional) supplier.get(); + return Objects.requireNonNull(r); } } diff --git a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java index 502b6a4bc79..0866f22eefd 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -63,7 +63,7 @@ import sun.util.ResourceBundleEnumeration; * files containing the resource data. ResourceBundle.getBundle * will automatically look for the appropriate properties file and create a * PropertyResourceBundle that refers to it. See - * {@link ResourceBundle#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) ResourceBundle.getBundle} + * {@link ResourceBundle#getBundle(String, Locale, ClassLoader) ResourceBundle.getBundle} * for a complete description of the search and instantiation strategy. * *

@@ -105,19 +105,14 @@ import sun.util.ResourceBundleEnumeration; *

* * - *

- * The implementation of a {@code PropertyResourceBundle} subclass must be - * thread-safe if it's simultaneously used by multiple threads. The default - * implementations of the non-abstract methods in this class are thread-safe. - * - *

- * Note: PropertyResourceBundle can be constructed either - * from an InputStream or a Reader, which represents a property file. - * Constructing a PropertyResourceBundle instance from an InputStream requires - * that the input stream be encoded in UTF-8. By default, if a + * @apiNote + * {@code PropertyResourceBundle} can be constructed either + * from an {@code InputStream} or a {@code Reader}, which represents a property file. + * Constructing a {@code PropertyResourceBundle} instance from an {@code InputStream} + * requires that the input stream be encoded in {@code UTF-8}. By default, if a * {@link java.nio.charset.MalformedInputException} or an * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the - * input stream, then the PropertyResourceBundle instance resets to the state + * input stream, then the {@code PropertyResourceBundle} instance resets to the state * before the exception, re-reads the input stream in {@code ISO-8859-1}, and * continues reading. If the system property * {@code java.util.PropertyResourceBundle.encoding} is set to either @@ -126,8 +121,15 @@ import sun.util.ResourceBundleEnumeration; * If "ISO-8859-1" is specified, characters that cannot be represented in * ISO-8859-1 encoding must be represented by Unicode Escapes as defined in section * 3.3 of The Java™ Language Specification - * whereas the other constructor which takes a Reader does not have that limitation. + * whereas the other constructor which takes a {@code Reader} does not have that limitation. * Other encoding values are ignored for this system property. + * The system property is read and evaluated when initializing this class. + * Changing or removing the property has no effect after the initialization. + * + * @implSpec + * The implementation of a {@code PropertyResourceBundle} subclass must be + * thread-safe if it's simultaneously used by multiple threads. The default + * implementations of the non-abstract methods in this class are thread-safe. * * @see ResourceBundle * @see ListResourceBundle @@ -144,16 +146,18 @@ public class PropertyResourceBundle extends ResourceBundle { /** * Creates a property resource bundle from an {@link java.io.InputStream - * InputStream}. This constructor reads the property file in UTF-8 by default. - * If a {@link java.nio.charset.MalformedInputException} or an - * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the - * input stream, then the PropertyResourceBundle instance resets to the state - * before the exception, re-reads the input stream in {@code ISO-8859-1} and - * continues reading. If the system property - * {@code java.util.PropertyResourceBundle.encoding} is set to either - * "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding, - * and throws the exception if it encounters an invalid sequence. Other - * encoding values are ignored for this system property. + * InputStream}. This constructor reads the property file in UTF-8 by default. + * If a {@link java.nio.charset.MalformedInputException} or an + * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the + * input stream, then the PropertyResourceBundle instance resets to the state + * before the exception, re-reads the input stream in {@code ISO-8859-1} and + * continues reading. If the system property + * {@code java.util.PropertyResourceBundle.encoding} is set to either + * "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding, + * and throws the exception if it encounters an invalid sequence. Other + * encoding values are ignored for this system property. + * The system property is read and evaluated when initializing this class. + * Changing or removing the property has no effect after the initialization. * * @param stream an InputStream that represents a property file * to read from. diff --git a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java index bc7aaae063e..1d84e2dee6b 100644 --- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java @@ -2491,34 +2491,29 @@ public abstract class ResourceBundle { /** * The default format List, which contains the strings * "java.class" and "java.properties", in - * this order. This List is {@linkplain - * Collections#unmodifiableList(List) unmodifiable}. + * this order. This List is unmodifiable. * * @see #getFormats(String) */ public static final List FORMAT_DEFAULT - = Collections.unmodifiableList(Arrays.asList("java.class", - "java.properties")); + = List.of("java.class", "java.properties"); /** * The class-only format List containing - * "java.class". This List is {@linkplain - * Collections#unmodifiableList(List) unmodifiable}. + * "java.class". This List is unmodifiable. * * @see #getFormats(String) */ - public static final List FORMAT_CLASS - = Collections.unmodifiableList(Arrays.asList("java.class")); + public static final List FORMAT_CLASS = List.of("java.class"); /** * The properties-only format List containing - * "java.properties". This List is - * {@linkplain Collections#unmodifiableList(List) unmodifiable}. + * "java.properties". This List is unmodifiable. * * @see #getFormats(String) */ public static final List FORMAT_PROPERTIES - = Collections.unmodifiableList(Arrays.asList("java.properties")); + = List.of("java.properties"); /** * The time-to-live constant for not caching loaded resource bundle diff --git a/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java b/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java index 850f1df24ee..1d96cd1f326 100644 --- a/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java +++ b/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java @@ -56,8 +56,8 @@ public interface ToolProvider { /** * Returns the name of this tool provider. * - * @apiNote It is recommended that the name be the same as would be used on - * the command line: for example, "javac", "jar", "jlink". + * @apiNote It is recommended that the name be the same as would be + * used on the command line: for example, "javac", "jar", "jlink". * * @return the name of this tool provider */ @@ -67,12 +67,13 @@ public interface ToolProvider { * Runs an instance of the tool, returning zero for a successful run. * Any non-zero return value indicates a tool-specific error during the * execution. + * * Two streams should be provided, for "expected" output, and for any * error messages. If it is not necessary to distinguish the output, * the same stream may be used for both. * * @apiNote The interpretation of the arguments will be specific to - * each tool. + * each tool. * * @param out a stream to which "expected" output should be written * @@ -81,12 +82,13 @@ public interface ToolProvider { * @param args the command-line arguments for the tool * * @return the result of executing the tool. - * A return value of 0 means the tool did not encounter any errors; - * any other value indicates that at least one error occurred during - * execution. + * A return value of 0 means the tool did not encounter any errors; + * any other value indicates that at least one error occurred + * during execution. * * @throws NullPointerException if any of the arguments are {@code null}, - * or if there are any {@code null} values in the {@code args} array + * or if there are any {@code null} values in the {@code args} + * array */ int run(PrintWriter out, PrintWriter err, String... args); @@ -94,16 +96,17 @@ public interface ToolProvider { * Runs an instance of the tool, returning zero for a successful run. * Any non-zero return value indicates a tool-specific error during the * execution. + * * Two streams should be provided, for "expected" output, and for any * error messages. If it is not necessary to distinguish the output, * the same stream may be used for both. * * @apiNote The interpretation of the arguments will be specific to - * each tool. + * each tool. * * @implNote This implementation wraps the {@code out} and {@code err} - * streams within {@link PrintWriter}s, and then calls - * {@link run(PrintWriter, PrintWriter, String[])}. + * streams within {@link PrintWriter}s, and then calls + * {@link #run(PrintWriter, PrintWriter, String[])}. * * @param out a stream to which "expected" output should be written * @@ -112,12 +115,13 @@ public interface ToolProvider { * @param args the command-line arguments for the tool * * @return the result of executing the tool. - * A return value of 0 means the tool did not encounter any errors; - * any other value indicates that at least one error occurred during - * execution. + * A return value of 0 means the tool did not encounter any errors; + * any other value indicates that at least one error occurred + * during execution. * * @throws NullPointerException if any of the arguments are {@code null}, - * or if there are any {@code null} values in the {@code args} array + * or if there are any {@code null} values in the {@code args} + * array */ default int run(PrintStream out, PrintStream err, String... args) { Objects.requireNonNull(out); diff --git a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java index 018bb5fc1b6..fd7b0a477fa 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java @@ -27,7 +27,6 @@ package java.util.stream; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -1720,12 +1719,12 @@ public final class Collectors { @Override public Set> entrySet() { - return new AbstractSet>() { + return new AbstractSet<>() { @Override public Iterator> iterator() { Map.Entry falseEntry = new SimpleImmutableEntry<>(false, forFalse); Map.Entry trueEntry = new SimpleImmutableEntry<>(true, forTrue); - return Arrays.asList(falseEntry, trueEntry).iterator(); + return List.of(falseEntry, trueEntry).iterator(); } @Override diff --git a/jdk/src/java.base/share/classes/java/util/stream/Stream.java b/jdk/src/java.base/share/classes/java/util/stream/Stream.java index 62ed4c82b6e..1ec21ed2b57 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java @@ -282,7 +282,7 @@ public interface Stream extends BaseStream> { */ Stream flatMap(Function> mapper); - /**: + /** * Returns an {@code IntStream} consisting of the results of replacing each * element of this stream with the contents of a mapped stream produced by * applying the provided mapping function to each element. Each mapped diff --git a/jdk/src/java.base/share/classes/jdk/internal/jmod/JmodFile.java b/jdk/src/java.base/share/classes/jdk/internal/jmod/JmodFile.java index 1d6ccbaf6c2..f64ccf2aa4a 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jmod/JmodFile.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jmod/JmodFile.java @@ -71,7 +71,9 @@ public class JmodFile implements AutoCloseable { NATIVE_LIBS("native"), NATIVE_CMDS("bin"), CLASSES("classes"), - CONFIG("conf"); + CONFIG("conf"), + HEADER_FILES("include"), + MAN_PAGES("man"); private final String jmodDir; private Section(String jmodDir) { @@ -151,6 +153,10 @@ public class JmodFile implements AutoCloseable { return Section.CLASSES; case "conf": return Section.CONFIG; + case "include": + return Section.HEADER_FILES; + case "man": + return Section.MAN_PAGES; default: throw new IllegalArgumentException("invalid section: " + s); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetInetAddressAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetInetAddressAccess.java index 34754d474b7..fdb25fee947 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetInetAddressAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetInetAddressAccess.java @@ -26,6 +26,7 @@ package jdk.internal.misc; import java.net.InetAddress; +import java.net.UnknownHostException; public interface JavaNetInetAddressAccess { /** @@ -33,4 +34,13 @@ public interface JavaNetInetAddressAccess { * the given InetAddress object. */ String getOriginalHostName(InetAddress ia); + + /** + * Get the InetAddress of the provided host. If an InetAddress is provided + * then it will be the default address returned for all calls to either + * form of getByName. This is required to maintain consistency when + * caching addresses and hostnames. + */ + InetAddress getByName(String hostName, InetAddress hostAddress) + throws UnknownHostException; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetURLClassLoaderAccess.java similarity index 80% rename from jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetAccess.java rename to jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetURLClassLoaderAccess.java index b8604b69341..c3d92c7ed9b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetURLClassLoaderAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,8 @@ package jdk.internal.misc; import java.net.URLClassLoader; -import jdk.internal.loader.URLClassPath; +import java.security.AccessControlContext; -public interface JavaNetAccess { - /** - * return the URLClassPath belonging to the given loader - */ - URLClassPath getURLClassPath (URLClassLoader u); +public interface JavaNetURLClassLoaderAccess { + AccessControlContext getAccessControlContext(URLClassLoader u);; } diff --git a/nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetUriAccess.java similarity index 80% rename from nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java rename to jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetUriAccess.java index 4a62bfaa046..53fd724502c 100644 --- a/nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetUriAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * 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,9 +23,13 @@ * questions. */ -package jdk.dynalink.test; +package jdk.internal.misc; -import jdk.dynalink.Operation; +import java.net.URI; -public final class TestLinkerOperation implements Operation { +public interface JavaNetUriAccess { + /** + * Create a URI of pre-validated scheme and path. + */ + URI create(String scheme, String path); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaSecurityAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaSecurityAccess.java index 3de82542b07..833a01b7c1d 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaSecurityAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaSecurityAccess.java @@ -27,6 +27,7 @@ package jdk.internal.misc; import java.security.AccessControlContext; import java.security.PrivilegedAction; +import java.security.ProtectionDomain; public interface JavaSecurityAccess { @@ -37,4 +38,5 @@ public interface JavaSecurityAccess { T doIntersectionPrivilege(PrivilegedAction action, AccessControlContext context); + ProtectionDomain[] getProtectDomains(AccessControlContext context); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index fda0d9f764c..d16ce84d3aa 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -53,10 +53,11 @@ public class SharedSecrets { private static JavaLangInvokeAccess javaLangInvokeAccess; private static JavaLangRefAccess javaLangRefAccess; private static JavaIOAccess javaIOAccess; - private static JavaNetAccess javaNetAccess; private static JavaNetInetAddressAccess javaNetInetAddressAccess; private static JavaNetHttpCookieAccess javaNetHttpCookieAccess; private static JavaNetSocketAccess javaNetSocketAccess; + private static JavaNetUriAccess javaNetUriAccess; + private static JavaNetURLClassLoaderAccess javaNetURLClassLoaderAccess; private static JavaNioAccess javaNioAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaIOFilePermissionAccess javaIOFilePermissionAccess; @@ -134,14 +135,24 @@ public class SharedSecrets { return javaLangRefAccess; } - public static void setJavaNetAccess(JavaNetAccess jna) { - javaNetAccess = jna; + public static void setJavaNetUriAccess(JavaNetUriAccess jnua) { + javaNetUriAccess = jnua; } - public static JavaNetAccess getJavaNetAccess() { - if (javaNetAccess == null) + public static JavaNetUriAccess getJavaNetUriAccess() { + if (javaNetUriAccess == null) + unsafe.ensureClassInitialized(java.net.URI.class); + return javaNetUriAccess; + } + + public static void setJavaNetURLClassLoaderAccess(JavaNetURLClassLoaderAccess jnua) { + javaNetURLClassLoaderAccess = jnua; + } + + public static JavaNetURLClassLoaderAccess getJavaNetURLClassLoaderAccess() { + if (javaNetURLClassLoaderAccess == null) unsafe.ensureClassInitialized(java.net.URLClassLoader.class); - return javaNetAccess; + return javaNetURLClassLoaderAccess; } public static void setJavaNetInetAddressAccess(JavaNetInetAddressAccess jna) { diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index 63c688ca171..b97c5f6da8c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -84,9 +84,22 @@ public class Reflection { public static native int getClassAccessFlags(Class c); + /** + * Ensures that access to a member is granted and throws + * IllegalAccessException if not. + * + * @param currentClass the class performing the access + * @param memberClass the declaring class of the member being accessed + * @param targetClass the class of target object if accessing instance + * field or method; + * or the declaring class if accessing constructor; + * or null if accessing static field or method + * @param modifiers the member's access modifiers + * @throws IllegalAccessException if access to member is denied + */ public static void ensureMemberAccess(Class currentClass, Class memberClass, - Object target, + Class targetClass, int modifiers) throws IllegalAccessException { @@ -94,18 +107,15 @@ public class Reflection { throw new InternalError(); } - if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) { - throwIllegalAccessException(currentClass, memberClass, target, modifiers); + if (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) { + throwIllegalAccessException(currentClass, memberClass, targetClass, modifiers); } } - public static boolean verifyMemberAccess(Class currentClass, - // Declaring class of field - // or method - Class memberClass, - // May be NULL in case of statics - Object target, - int modifiers) + private static boolean verifyMemberAccess(Class currentClass, + Class memberClass, + Class targetClass, + int modifiers) { // Verify that currentClass can access a field, method, or // constructor of memberClass, where that member's access bits are @@ -162,18 +172,18 @@ public class Reflection { return false; } - if (Modifier.isProtected(modifiers)) { - // Additional test for protected members: JLS 6.6.2 - Class targetClass = (target == null ? memberClass : target.getClass()); - if (targetClass != currentClass) { - if (!gotIsSameClassPackage) { - isSameClassPackage = isSameClassPackage(currentClass, memberClass); - gotIsSameClassPackage = true; - } - if (!isSameClassPackage) { - if (!isSubclassOf(targetClass, currentClass)) { - return false; - } + // Additional test for protected instance members + // and protected constructors: JLS 6.6.2 + if (targetClass != null && Modifier.isProtected(modifiers) && + targetClass != currentClass) + { + if (!gotIsSameClassPackage) { + isSameClassPackage = isSameClassPackage(currentClass, memberClass); + gotIsSameClassPackage = true; + } + if (!isSameClassPackage) { + if (!isSubclassOf(targetClass, currentClass)) { + return false; } } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java index a18437d0ed1..4b98f4c91bf 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * 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,14 +25,25 @@ package jdk.internal.reflect; +import java.io.Externalizable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.OptionalDataException; +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.security.Permission; import java.security.PrivilegedAction; +import java.util.Objects; import java.util.Properties; + import sun.reflect.misc.ReflectUtil; import sun.security.action.GetPropertyAction; @@ -57,6 +68,9 @@ public class ReflectionFactory { // Provides access to package-private mechanisms in java.lang.reflect private static volatile LangReflectAccess langReflectAccess; + /* Method for static class initializer , or null */ + private static volatile Method hasStaticInitializerMethod; + // // "Inflation" mechanism. Loading bytecodes to implement // Method.invoke() and Constructor.newInstance() currently costs @@ -337,16 +351,41 @@ public class ReflectionFactory { // // - public Constructor newConstructorForSerialization - (Class classToInstantiate, Constructor constructorToCall) - { - // Fast path - if (constructorToCall.getDeclaringClass() == classToInstantiate) { - return constructorToCall; + public final Constructor newConstructorForExternalization(Class cl) { + if (!Externalizable.class.isAssignableFrom(cl)) { + return null; + } + try { + Constructor cons = cl.getConstructor(); + cons.setAccessible(true); + return cons; + } catch (NoSuchMethodException ex) { + return null; + } + } + + public final Constructor newConstructorForSerialization(Class cl) { + Class initCl = cl; + while (Serializable.class.isAssignableFrom(initCl)) { + if ((initCl = initCl.getSuperclass()) == null) { + return null; + } + } + Constructor constructorToCall; + try { + constructorToCall = initCl.getDeclaredConstructor(); + int mods = constructorToCall.getModifiers(); + if ((mods & Modifier.PRIVATE) != 0 || + ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && + !packageEquals(cl, initCl))) { + return null; + } + } catch (NoSuchMethodException ex) { + return null; } ConstructorAccessor acc = new MethodAccessorGenerator(). - generateSerializationConstructor(classToInstantiate, + generateSerializationConstructor(cl, constructorToCall.getParameterTypes(), constructorToCall.getExceptionTypes(), constructorToCall.getModifiers(), @@ -364,9 +403,151 @@ public class ReflectionFactory { langReflectAccess(). getConstructorParameterAnnotations(constructorToCall)); setConstructorAccessor(c, acc); + c.setAccessible(true); return c; } + public final MethodHandle readObjectForSerialization(Class cl) { + return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class); + } + + public final MethodHandle readObjectNoDataForSerialization(Class cl) { + return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class); + } + + public final MethodHandle writeObjectForSerialization(Class cl) { + return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class); + } + + private final MethodHandle findReadWriteObjectForSerialization(Class cl, + String methodName, + Class streamClass) { + if (!Serializable.class.isAssignableFrom(cl)) { + return null; + } + + try { + Method meth = cl.getDeclaredMethod(methodName, streamClass); + int mods = meth.getModifiers(); + if (meth.getReturnType() != Void.TYPE || + Modifier.isStatic(mods) || + !Modifier.isPrivate(mods)) { + return null; + } + meth.setAccessible(true); + return MethodHandles.lookup().unreflect(meth); + } catch (NoSuchMethodException ex) { + return null; + } catch (IllegalAccessException ex1) { + throw new InternalError("Error", ex1); + } + } + + /** + * Returns a MethodHandle for {@code writeReplace} on the serializable class + * or null if no match found. + * @param cl a serializable class + * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found + */ + public final MethodHandle writeReplaceForSerialization(Class cl) { + return getReplaceResolveForSerialization(cl, "writeReplace"); + } + + /** + * Returns a MethodHandle for {@code readResolve} on the serializable class + * or null if no match found. + * @param cl a serializable class + * @returns the {@code writeReplace} MethodHandle or {@code null} if not found + */ + public final MethodHandle readResolveForSerialization(Class cl) { + return getReplaceResolveForSerialization(cl, "readResolve"); + } + + /** + * Lookup readResolve or writeReplace on a class with specified + * signature constraints. + * @param cl a serializable class + * @param methodName the method name to find + * @returns a MethodHandle for the method or {@code null} if not found or + * has the wrong signature. + */ + private MethodHandle getReplaceResolveForSerialization(Class cl, + String methodName) { + if (!Serializable.class.isAssignableFrom(cl)) { + return null; + } + + Class defCl = cl; + while (defCl != null) { + try { + Method m = defCl.getDeclaredMethod(methodName); + if (m.getReturnType() != Object.class) { + return null; + } + int mods = m.getModifiers(); + if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) { + return null; + } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) { + // fall through + } else if (Modifier.isPrivate(mods) && (cl != defCl)) { + return null; + } else if (!packageEquals(cl, defCl)) { + return null; + } + try { + // Normal return + m.setAccessible(true); + return MethodHandles.lookup().unreflect(m); + } catch (IllegalAccessException ex0) { + // setAccessible should prevent IAE + throw new InternalError("Error", ex0); + } + } catch (NoSuchMethodException ex) { + defCl = defCl.getSuperclass(); + } + } + return null; + } + + /** + * Returns true if the given class defines a static initializer method, + * false otherwise. + */ + public final boolean hasStaticInitializerForSerialization(Class cl) { + Method m = hasStaticInitializerMethod; + if (m == null) { + try { + m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", + new Class[]{Class.class}); + m.setAccessible(true); + hasStaticInitializerMethod = m; + } catch (NoSuchMethodException ex) { + throw new InternalError("No such method hasStaticInitializer on " + + ObjectStreamClass.class, ex); + } + } + try { + return (Boolean) m.invoke(null, cl); + } catch (InvocationTargetException | IllegalAccessException ex) { + throw new InternalError("Exception invoking hasStaticInitializer", ex); + } + } + + /** + * Return the accessible constructor for OptionalDataException signaling eof. + * @returns the eof constructor for OptionalDataException + */ + public final Constructor newOptionalDataExceptionForSerialization() { + try { + Constructor boolCtor = + OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE); + boolCtor.setAccessible(true); + return boolCtor; + } catch (NoSuchMethodException ex) { + throw new InternalError("Constructor not found", ex); + } + } + //-------------------------------------------------------------------------- // // Internals only below this point @@ -426,4 +607,17 @@ public class ReflectionFactory { } return langReflectAccess; } + + /** + * Returns true if classes are defined in the classloader and same package, false + * otherwise. + * @param cl1 a class + * @param cl2 another class + * @returns true if the two classes are in the same classloader and package + */ + private static boolean packageEquals(Class cl1, Class cl2) { + return cl1.getClassLoader() == cl2.getClassLoader() && + Objects.equals(cl1.getPackage(), cl2.getPackage()); + } + } diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 4cb223881bc..7b76d703cc4 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -154,7 +154,6 @@ module java.base { exports jdk.internal.module to java.instrument, java.management, - jdk.dynalink, jdk.jartool, jdk.jlink; exports jdk.internal.misc to @@ -172,8 +171,10 @@ module java.base { jdk.jartool, jdk.jdeps, jdk.jlink, + jdk.jshell, jdk.net, jdk.scripting.nashorn, + jdk.scripting.nashorn.shell, jdk.unsupported, jdk.vm.ci; exports jdk.internal.perf to @@ -239,8 +240,7 @@ module java.base { java.xml.ws; exports sun.security.action to java.desktop, - java.security.jgss, - jdk.crypto.pkcs11; + java.security.jgss; exports sun.security.internal.interfaces to jdk.crypto.pkcs11; exports sun.security.internal.spec to @@ -266,6 +266,8 @@ module java.base { jdk.crypto.pkcs11; exports sun.security.ssl to java.security.jgss; + exports sun.security.timestamp to + jdk.jartool; exports sun.security.tools to jdk.jartool; exports sun.security.util to diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index 6bcd152fdd1..dbfc04b7d59 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -25,8 +25,11 @@ package sun.net.www.protocol.http; +import java.util.Collections; import java.util.Iterator; import java.util.HashMap; +import java.util.Set; + import sun.net.www.*; import sun.security.action.GetPropertyAction; @@ -67,8 +70,8 @@ import sun.security.action.GetPropertyAction; * -Dhttp.auth.preference="scheme" * * which in this case, specifies that "scheme" should be used as the auth scheme when offered - * disregarding the default prioritisation. If scheme is not offered then the default priority - * is used. + * disregarding the default prioritisation. If scheme is not offered, or explicitly + * disabled, by {@code disabledSchemes}, then the default priority is used. * * Attention: when http.auth.preference is set as SPNEGO or Kerberos, it's actually "Negotiate * with SPNEGO" or "Negotiate with Kerberos", which means the user will prefer the Negotiate @@ -113,17 +116,32 @@ public class AuthenticationHeader { String hdrname; // Name of the header to look for /** - * parse a set of authentication headers and choose the preferred scheme - * that we support for a given host + * Parses a set of authentication headers and chooses the preferred scheme + * that is supported for a given host. */ public AuthenticationHeader (String hdrname, MessageHeader response, HttpCallerInfo hci, boolean dontUseNegotiate) { + this(hdrname, response, hci, dontUseNegotiate, Collections.emptySet()); + } + + /** + * Parses a set of authentication headers and chooses the preferred scheme + * that is supported for a given host. + * + *

The {@code disabledSchemes} parameter is a, possibly empty, set of + * authentication schemes that are disabled. + */ + public AuthenticationHeader(String hdrname, + MessageHeader response, + HttpCallerInfo hci, + boolean dontUseNegotiate, + Set disabledSchemes) { this.hci = hci; this.dontUseNegotiate = dontUseNegotiate; - rsp = response; + this.rsp = response; this.hdrname = hdrname; - schemes = new HashMap<>(); - parse(); + this.schemes = new HashMap<>(); + parse(disabledSchemes); } public HttpCallerInfo getHttpCallerInfo() { @@ -143,10 +161,11 @@ public class AuthenticationHeader { * then the last one will be used. The * preferred scheme that we support will be used. */ - private void parse () { + private void parse(Set disabledSchemes) { Iterator iter = rsp.multiValueIterator(hdrname); while (iter.hasNext()) { String raw = iter.next(); + // HeaderParser lower cases everything, so can be used case-insensitively HeaderParser hp = new HeaderParser(raw); Iterator keys = hp.keys(); int i, lastSchemeIndex; @@ -156,7 +175,8 @@ public class AuthenticationHeader { if (lastSchemeIndex != -1) { HeaderParser hpn = hp.subsequence (lastSchemeIndex, i); String scheme = hpn.findKey(0); - schemes.put (scheme, new SchemeMapValue (hpn, raw)); + if (!disabledSchemes.contains(scheme)) + schemes.put(scheme, new SchemeMapValue (hpn, raw)); } lastSchemeIndex = i; } @@ -164,7 +184,8 @@ public class AuthenticationHeader { if (i > lastSchemeIndex) { HeaderParser hpn = hp.subsequence (lastSchemeIndex, i); String scheme = hpn.findKey(0); - schemes.put(scheme, new SchemeMapValue (hpn, raw)); + if (!disabledSchemes.contains(scheme)) + schemes.put(scheme, new SchemeMapValue (hpn, raw)); } } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 35a3fa5da66..058de37b3b8 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -25,6 +25,7 @@ package sun.net.www.protocol.http; +import java.security.PrivilegedAction; import java.util.Arrays; import java.net.URL; import java.net.URLConnection; @@ -109,6 +110,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { static final boolean validateProxy; static final boolean validateServer; + /** A, possibly empty, set of authentication schemes that are disabled + * when proxying plain HTTP ( not HTTPS ). */ + static final Set disabledProxyingSchemes; + + /** A, possibly empty, set of authentication schemes that are disabled + * when setting up a tunnel for HTTPS ( HTTP CONNECT ). */ + static final Set disabledTunnelingSchemes; + private StreamingOutputStream strOutputStream; private static final String RETRY_MSG1 = "cannot retry due to proxy authentication, in streaming mode"; @@ -206,6 +215,22 @@ public class HttpURLConnection extends java.net.HttpURLConnection { "Via" }; + private static String getNetProperty(String name) { + PrivilegedAction pa = () -> NetProperties.get(name); + return AccessController.doPrivileged(pa); + } + + private static Set schemesListToSet(String list) { + if (list == null || list.isEmpty()) + return Collections.emptySet(); + + Set s = new HashSet<>(); + String[] parts = list.split("\\s*,\\s*"); + for (String part : parts) + s.add(part.toLowerCase(Locale.ROOT)); + return s; + } + static { Properties props = GetPropertyAction.privilegedGetProperties(); maxRedirects = GetIntegerAction.privilegedGetProperty( @@ -218,6 +243,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { agent = agent + " Java/"+version; } userAgent = agent; + + // A set of net properties to control the use of authentication schemes + // when proxing/tunneling. + String p = getNetProperty("jdk.http.auth.tunneling.disabledSchemes"); + disabledTunnelingSchemes = schemesListToSet(p); + p = getNetProperty("jdk.http.auth.proxying.disabledSchemes"); + disabledProxyingSchemes = schemesListToSet(p); + validateProxy = Boolean.parseBoolean( props.getProperty("http.auth.digest.validateProxy")); validateServer = Boolean.parseBoolean( @@ -1575,10 +1608,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection { // altered in similar ways. AuthenticationHeader authhdr = new AuthenticationHeader ( - "Proxy-Authenticate", responses, - new HttpCallerInfo(url, http.getProxyHostUsed(), - http.getProxyPortUsed()), - dontUseNegotiate + "Proxy-Authenticate", + responses, + new HttpCallerInfo(url, + http.getProxyHostUsed(), + http.getProxyPortUsed()), + dontUseNegotiate, + disabledProxyingSchemes ); if (!doingNTLMp2ndStage) { @@ -2024,11 +2060,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } - AuthenticationHeader authhdr = new AuthenticationHeader ( - "Proxy-Authenticate", responses, - new HttpCallerInfo(url, http.getProxyHostUsed(), - http.getProxyPortUsed()), - dontUseNegotiate + AuthenticationHeader authhdr = new AuthenticationHeader( + "Proxy-Authenticate", + responses, + new HttpCallerInfo(url, + http.getProxyHostUsed(), + http.getProxyPortUsed()), + dontUseNegotiate, + disabledTunnelingSchemes ); if (!doingNTLMp2ndStage) { proxyAuthentication = diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java index ed920e74ade..1b166447b78 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java @@ -432,6 +432,8 @@ public class HKSCS { continue; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); + if (c == UNMAPPABLE_DECODING) + continue; int hi = c >> 8; if (c2b[hi] == C2B_UNMAPPABLE) { c2b[hi] = new char[0x100]; diff --git a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java index 07f53c490b5..c275b0b91a6 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java @@ -44,9 +44,21 @@ public final class ReflectUtil { return Class.forName(name); } - /* - * Reflection.ensureMemberAccess is overly-restrictive - * due to a bug. We awkwardly work around it for now. + /** + * Ensures that access to a method or field is granted and throws + * IllegalAccessException if not. This method is not suitable for checking + * access to constructors. + * + * @param currentClass the class performing the access + * @param memberClass the declaring class of the member being accessed + * @param target the target object if accessing instance field or method; + * or null if accessing static field or method or if target + * object access rights will be checked later + * @param modifiers the member's access modifiers + * @throws IllegalAccessException if access to member is denied + * @implNote Delegates directly to + * {@link Reflection#ensureMemberAccess(Class, Class, Class, int)} + * which should be used instead. */ public static void ensureMemberAccess(Class currentClass, Class memberClass, @@ -54,62 +66,10 @@ public final class ReflectUtil { int modifiers) throws IllegalAccessException { - if (target == null && Modifier.isProtected(modifiers)) { - int mods = modifiers; - mods = mods & (~Modifier.PROTECTED); - mods = mods | Modifier.PUBLIC; - - /* - * See if we fail because of class modifiers - */ - Reflection.ensureMemberAccess(currentClass, - memberClass, - target, - mods); - try { - /* - * We're still here so class access was ok. - * Now try with default field access. - */ - mods = mods & (~Modifier.PUBLIC); - Reflection.ensureMemberAccess(currentClass, - memberClass, - target, - mods); - /* - * We're still here so access is ok without - * checking for protected. - */ - return; - } catch (IllegalAccessException e) { - /* - * Access failed but we're 'protected' so - * if the test below succeeds then we're ok. - */ - if (isSubclassOf(currentClass, memberClass)) { - return; - } else { - throw e; - } - } - } else { - Reflection.ensureMemberAccess(currentClass, - memberClass, - target, - modifiers); - } - } - - private static boolean isSubclassOf(Class queryClass, - Class ofClass) - { - while (queryClass != null) { - if (queryClass == ofClass) { - return true; - } - queryClass = queryClass.getSuperclass(); - } - return false; + Reflection.ensureMemberAccess(currentClass, + memberClass, + target == null ? null : target.getClass(), + modifiers); } /** diff --git a/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java b/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java index c6f606ece80..ed69ba3d8b9 100644 --- a/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java +++ b/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,20 +28,38 @@ package sun.security.pkcs; import java.io.OutputStream; import java.io.IOException; import java.math.BigInteger; +import java.security.CryptoPrimitive; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Principal; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.Timestamp; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CertPath; import java.security.cert.X509Certificate; -import java.security.*; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Set; import sun.security.timestamp.TimestampToken; -import sun.security.util.*; +import sun.security.util.Debug; +import sun.security.util.DerEncoder; +import sun.security.util.DerInputStream; +import sun.security.util.DerOutputStream; +import sun.security.util.DerValue; +import sun.security.util.DisabledAlgorithmConstraints; +import sun.security.util.HexDumpEncoder; +import sun.security.util.KeyUtil; +import sun.security.util.ObjectIdentifier; import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; import sun.security.x509.KeyUsageExtension; -import sun.security.util.HexDumpEncoder; /** * A SignerInfo, as defined in PKCS#7's signedData type. @@ -50,6 +68,17 @@ import sun.security.util.HexDumpEncoder; */ public class SignerInfo implements DerEncoder { + // Digest and Signature restrictions + private static final Set DIGEST_PRIMITIVE_SET = + Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); + + private static final Set SIG_PRIMITIVE_SET = + Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); + + private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK = + new DisabledAlgorithmConstraints( + DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); + BigInteger version; X500Name issuerName; BigInteger certificateSerialNumber; @@ -318,6 +347,13 @@ public class SignerInfo implements DerEncoder { if (messageDigest == null) // fail if there is no message digest return null; + // check that algorithm is not restricted + if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, + digestAlgname, null)) { + throw new SignatureException("Digest check failed. " + + "Disabled algorithm used: " + digestAlgname); + } + MessageDigest md = MessageDigest.getInstance(digestAlgname); byte[] computedMessageDigest = md.digest(data); @@ -349,12 +385,26 @@ public class SignerInfo implements DerEncoder { String algname = AlgorithmId.makeSigAlg( digestAlgname, encryptionAlgname); - Signature sig = Signature.getInstance(algname); - X509Certificate cert = getCertificate(block); + // check that algorithm is not restricted + if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, algname, null)) { + throw new SignatureException("Signature check failed. " + + "Disabled algorithm used: " + algname); + } + X509Certificate cert = getCertificate(block); + PublicKey key = cert.getPublicKey(); if (cert == null) { return null; } + + // check if the public key is restricted + if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { + throw new SignatureException("Public key check failed. " + + "Disabled key used: " + + KeyUtil.getKeySize(key) + " bit " + + key.getAlgorithm()); + } + if (cert.hasUnsupportedCriticalExtension()) { throw new SignatureException("Certificate has unsupported " + "critical extension(s)"); @@ -391,11 +441,9 @@ public class SignerInfo implements DerEncoder { } } - PublicKey key = cert.getPublicKey(); + Signature sig = Signature.getInstance(algname); sig.initVerify(key); - sig.update(dataSigned); - if (sig.verify(encryptedDigest)) { return this; } @@ -450,6 +498,23 @@ public class SignerInfo implements DerEncoder { return unauthenticatedAttributes; } + /** + * Returns the timestamp PKCS7 data unverified. + * @return a PKCS7 object + */ + public PKCS7 getTsToken() throws IOException { + if (unauthenticatedAttributes == null) { + return null; + } + PKCS9Attribute tsTokenAttr = + unauthenticatedAttributes.getAttribute( + PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); + if (tsTokenAttr == null) { + return null; + } + return new PKCS7((byte[])tsTokenAttr.getValue()); + } + /* * Extracts a timestamp from a PKCS7 SignerInfo. * @@ -477,19 +542,12 @@ public class SignerInfo implements DerEncoder { if (timestamp != null || !hasTimestamp) return timestamp; - if (unauthenticatedAttributes == null) { - hasTimestamp = false; - return null; - } - PKCS9Attribute tsTokenAttr = - unauthenticatedAttributes.getAttribute( - PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); - if (tsTokenAttr == null) { + PKCS7 tsToken = getTsToken(); + if (tsToken == null) { hasTimestamp = false; return null; } - PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue()); // Extract the content (an encoded timestamp token info) byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); // Extract the signer (the Timestamping Authority) @@ -515,9 +573,16 @@ public class SignerInfo implements DerEncoder { */ private void verifyTimestamp(TimestampToken token) throws NoSuchAlgorithmException, SignatureException { + String digestAlgname = token.getHashAlgorithm().getName(); + // check that algorithm is not restricted + if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, digestAlgname, + null)) { + throw new SignatureException("Timestamp token digest check failed. " + + "Disabled algorithm used: " + digestAlgname); + } MessageDigest md = - MessageDigest.getInstance(token.getHashAlgorithm().getName()); + MessageDigest.getInstance(digestAlgname); if (!Arrays.equals(token.getHashedMessage(), md.digest(encryptedDigest))) { diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java index d8f64cb7897..a4bb68150a5 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java @@ -185,20 +185,22 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { AlgorithmConstraints constraints, Date pkixdate) { - if (anchor == null) { - throw new IllegalArgumentException( - "The trust anchor cannot be null"); - } - - if (anchor.getTrustedCert() != null) { - this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); - // Check for anchor certificate restrictions - trustedMatch = checkFingerprint(anchor.getTrustedCert()); - if (trustedMatch && debug != null) { - debug.println("trustedMatch = true"); + if (anchor != null) { + if (anchor.getTrustedCert() != null) { + this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); + // Check for anchor certificate restrictions + trustedMatch = checkFingerprint(anchor.getTrustedCert()); + if (trustedMatch && debug != null) { + debug.println("trustedMatch = true"); + } + } else { + this.trustedPubKey = anchor.getCAPublicKey(); } } else { - this.trustedPubKey = anchor.getCAPublicKey(); + this.trustedPubKey = null; + if (debug != null) { + debug.println("TrustAnchor is null, trustedMatch is false."); + } } this.prevPubKey = trustedPubKey; diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 3c86d6206ff..56ecabfc4f3 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -816,18 +816,22 @@ class ForwardBuilder extends Builder { /** * Verifies whether the input certificate completes the path. - * Checks the cert against each trust anchor that was specified, in order, - * and returns true as soon as it finds a valid anchor. - * Returns true if the cert matches a trust anchor specified as a - * certificate or if the cert verifies with a trust anchor that - * was specified as a trusted {pubkey, caname} pair. Returns false if none - * of the trust anchors are valid for this cert. + * First checks the cert against each trust anchor that was specified, + * in order, and returns true if the cert matches the trust anchor + * specified as a certificate or has the same key and subject of an anchor + * specified as a trusted {pubkey, caname} pair. + * If no match has been found, does a second check of the cert against + * anchors specified as a trusted {pubkey, caname} pair to see if the cert + * was issued by that anchor. + * Returns false if none of the trust anchors are valid for this cert. * * @param cert the certificate to test * @return a boolean value indicating whether the cert completes the path. */ @Override boolean isPathCompleted(X509Certificate cert) { + List otherAnchors = new ArrayList<>(); + // first, check if cert is already trusted for (TrustAnchor anchor : trustAnchors) { if (anchor.getTrustedCert() != null) { if (cert.equals(anchor.getTrustedCert())) { @@ -849,7 +853,12 @@ class ForwardBuilder extends Builder { } // else, it is a self-issued certificate of the anchor } - + otherAnchors.add(anchor); + } + // next, check if cert is issued by anchor specified by key/name + for (TrustAnchor anchor : otherAnchors) { + X500Principal principal = anchor.getCA(); + PublicKey publicKey = anchor.getCAPublicKey(); // Check subject/issuer name chaining if (principal == null || !principal.equals(cert.getIssuerX500Principal())) { diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java index ad805e60b41..8753072e9d0 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java @@ -35,6 +35,7 @@ import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.CRLReason; import java.security.cert.Extension; +import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; @@ -163,6 +164,15 @@ public final class OCSP { X509Certificate responderCert, Date date, List extensions) throws IOException, CertPathValidatorException + { + return check(cert, responderURI, null, issuerCert, responderCert, date, extensions); + } + + public static RevocationStatus check(X509Certificate cert, + URI responderURI, TrustAnchor anchor, X509Certificate issuerCert, + X509Certificate responderCert, Date date, + List extensions) + throws IOException, CertPathValidatorException { CertId certId = null; try { @@ -173,8 +183,8 @@ public final class OCSP { ("Exception while encoding OCSPRequest", e); } OCSPResponse ocspResponse = check(Collections.singletonList(certId), - responderURI, new OCSPResponse.IssuerInfo(issuerCert), - responderCert, date, extensions); + responderURI, new OCSPResponse.IssuerInfo(anchor, issuerCert), + responderCert, date, extensions); return (RevocationStatus) ocspResponse.getSingleResponse(certId); } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java index a2b74d1bdeb..d1770da153a 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java @@ -507,9 +507,8 @@ public final class OCSPResponse { // Check algorithm constraints specified in security property // "jdk.certpath.disabledAlgorithms". - AlgorithmChecker algChecker = new AlgorithmChecker( - new TrustAnchor(issuerInfo.getName(), - issuerInfo.getPublicKey(), null)); + AlgorithmChecker algChecker = + new AlgorithmChecker(issuerInfo.getAnchor(), date); algChecker.init(false); algChecker.check(signerCert, Collections.emptySet()); @@ -982,36 +981,38 @@ public final class OCSPResponse { /** * Helper class that allows consumers to pass in issuer information. This * will always consist of the issuer's name and public key, but may also - * contain a certificate if the originating data is in that form. + * contain a certificate if the originating data is in that form. The + * trust anchor for the certificate chain will be included for certpath + * disabled algorithm checking. */ static final class IssuerInfo { + private final TrustAnchor anchor; private final X509Certificate certificate; private final X500Principal name; private final PublicKey pubKey; - IssuerInfo(X509Certificate issuerCert) { - certificate = Objects.requireNonNull(issuerCert, - "Constructor requires non-null certificate"); - name = certificate.getSubjectX500Principal(); - pubKey = certificate.getPublicKey(); - } - - IssuerInfo(X500Principal subjectName, PublicKey key) { - certificate = null; - name = Objects.requireNonNull(subjectName, - "Constructor requires non-null subject"); - pubKey = Objects.requireNonNull(key, - "Constructor requires non-null public key"); - } - IssuerInfo(TrustAnchor anchor) { - certificate = anchor.getTrustedCert(); - if (certificate != null) { - name = certificate.getSubjectX500Principal(); - pubKey = certificate.getPublicKey(); + this(anchor, (anchor != null) ? anchor.getTrustedCert() : null); + } + + IssuerInfo(X509Certificate issuerCert) { + this(null, issuerCert); + } + + IssuerInfo(TrustAnchor anchor, X509Certificate issuerCert) { + if (anchor == null && issuerCert == null) { + throw new NullPointerException("TrustAnchor and issuerCert " + + "cannot be null"); + } + this.anchor = anchor; + if (issuerCert != null) { + name = issuerCert.getSubjectX500Principal(); + pubKey = issuerCert.getPublicKey(); + certificate = issuerCert; } else { name = anchor.getCA(); pubKey = anchor.getCAPublicKey(); + certificate = anchor.getTrustedCert(); } } @@ -1046,6 +1047,15 @@ public final class OCSPResponse { return pubKey; } + /** + * Get the TrustAnchor for the certificate chain. + * + * @return a {@code TrustAnchor}. + */ + TrustAnchor getAnchor() { + return anchor; + } + /** * Create a string representation of this IssuerInfo. * diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java index e3de6a959e7..85e596cb6c3 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java @@ -437,7 +437,7 @@ class RevocationChecker extends PKIXRevocationChecker { private void updateState(X509Certificate cert) throws CertPathValidatorException { - issuerInfo = new OCSPResponse.IssuerInfo(cert); + issuerInfo = new OCSPResponse.IssuerInfo(anchor, cert); // Make new public key if parameters are missing PublicKey pubKey = cert.getPublicKey(); @@ -740,8 +740,8 @@ class RevocationChecker extends PKIXRevocationChecker { } response = OCSP.check(Collections.singletonList(certId), - responderURI, issuerInfo, - responderCert, null, ocspExtensions); + responderURI, issuerInfo, responderCert, params.date(), + ocspExtensions); } } catch (IOException e) { throw new CertPathValidatorException( diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java b/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java index 632d0da18f1..d4f2848c973 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java @@ -282,7 +282,7 @@ final class EllipticCurvesExtension extends HelloExtension { private static int getPreferredCurve(int[] curves, AlgorithmConstraints constraints) { for (int curveId : curves) { - if (constraints.permits( + if (isSupported(curveId) && constraints.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), "EC", idToParams.get(curveId))) { return curveId; diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java index b3740cfcd86..4717fbba178 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java @@ -49,6 +49,7 @@ import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; import sun.security.util.KeyUtil; +import sun.security.util.MessageDigestSpi2; import sun.security.provider.certpath.OCSPResponse; /** @@ -2124,63 +2125,14 @@ static final class CertificateVerify extends HandshakeMessage { md.update(temp); } - private static final Class delegate; - private static final Field spiField; - - static { - try { - delegate = Class.forName("java.security.MessageDigest$Delegate"); - spiField = delegate.getDeclaredField("digestSpi"); - } catch (Exception e) { - throw new RuntimeException("Reflection failed", e); - } - makeAccessible(spiField); - } - - private static void makeAccessible(final AccessibleObject o) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - o.setAccessible(true); - return null; - } - }); - } - - // ConcurrentHashMap does not allow null values, use this marker object - private static final Object NULL_OBJECT = new Object(); - - // cache Method objects per Spi class - // Note that this will prevent the Spi classes from being GC'd. We assume - // that is not a problem. - private static final Map,Object> methodCache = - new ConcurrentHashMap<>(); - private static void digestKey(MessageDigest md, SecretKey key) { try { - // Verify that md is implemented via MessageDigestSpi, not - // via JDK 1.1 style MessageDigest subclassing. - if (md.getClass() != delegate) { - throw new Exception("Digest is not a MessageDigestSpi"); - } - MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md); - Class clazz = spi.getClass(); - Object r = methodCache.get(clazz); - if (r == null) { - try { - r = clazz.getDeclaredMethod("implUpdate", SecretKey.class); - makeAccessible((Method)r); - } catch (NoSuchMethodException e) { - r = NULL_OBJECT; - } - methodCache.put(clazz, r); - } - if (r == NULL_OBJECT) { + if (md instanceof MessageDigestSpi2) { + ((MessageDigestSpi2)md).engineUpdate(key); + } else { throw new Exception( "Digest does not support implUpdate(SecretKey)"); } - Method update = (Method)r; - update.invoke(spi, key); } catch (Exception e) { throw new RuntimeException( "Could not obtain encoded key and " diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index c68e7431053..a8870960ca6 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1172,11 +1172,18 @@ final class ServerHandshaker extends Handshaker { if (trySetCipherSuite(suite) == false) { continue; } + + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Standard ciphersuite chosen: " + suite); + } return; } for (CipherSuite suite : legacySuites) { if (trySetCipherSuite(suite)) { + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Legacy ciphersuite chosen: " + suite); + } return; } } diff --git a/jdk/src/java.base/share/classes/sun/security/util/CurveDB.java b/jdk/src/java.base/share/classes/sun/security/util/CurveDB.java index 197d5a618db..07e100ff03e 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/CurveDB.java +++ b/jdk/src/java.base/share/classes/sun/security/util/CurveDB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -664,6 +664,74 @@ public class CurveDB { 0xFF70, nameSplitPattern); */ + /* + * Brainpool curves (RFC 5639) + * (Twisted curves are not included) + */ + + add("brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1", P, + "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", + "1E589A8595423412134FAA2DBDEC95C8D8675E58", + "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", + "1667CB477A1A8EC338F94741669C976316DA6321", + "E95E4A5F737059DC60DF5991D45029409E60FC09", + 1, nameSplitPattern); + + add("brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", P, + "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", + "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", + "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", + "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", + "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + 1, nameSplitPattern); + + add("brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", P, + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", + "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + 1, nameSplitPattern); + + add("brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", P, + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + 1, nameSplitPattern); + + add("brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", P, + "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", + "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", + "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", + "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", + "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + 1, nameSplitPattern); + + add("brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", P, + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + 1, nameSplitPattern); + + add("brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", P, + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + 1, nameSplitPattern); + specCollection = Collections.unmodifiableCollection(oidMap.values()); } } diff --git a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index a77eabe675c..737d68f4881 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -60,6 +60,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { public static final String PROPERTY_TLS_DISABLED_ALGS = "jdk.tls.disabledAlgorithms"; + // the known security property, jdk.jar.disabledAlgorithms + public static final String PROPERTY_JAR_DISABLED_ALGS = + "jdk.jar.disabledAlgorithms"; + private final String[] disabledAlgorithms; private final Constraints algorithmConstraints; @@ -73,6 +77,14 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { this(propertyName, new AlgorithmDecomposer()); } + /** + * Initialize algorithm constraints with the specified security property + * for a specific usage type. + * + * @param propertyName the security property name that define the disabled + * algorithm constraints + * @param decomposer an alternate AlgorithmDecomposer. + */ public DisabledAlgorithmConstraints(String propertyName, AlgorithmDecomposer decomposer) { super(decomposer); @@ -530,7 +542,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { } throw new CertPathValidatorException( "Algorithm constraints check failed on certificate " + - "anchor limits", + "anchor limits. " + algorithm + " used with " + + cp.getCertificate().getSubjectX500Principal(), null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } @@ -611,8 +624,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return; } throw new CertPathValidatorException( - "denyAfter constraint check failed. " + - "Constraint date: " + + "denyAfter constraint check failed: " + algorithm + + " used with Constraint date: " + dateFormat.format(denyAfterDate) + "; " + errmsg + dateFormat.format(currentDate), null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); @@ -644,6 +657,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { private int minSize; // the minimal available key size private int maxSize; // the maximal available key size private int prohibitedSize = -1; // unavailable key sizes + private int size; public KeySizeConstraint(String algo, Operator operator, int length) { algorithm = algo; @@ -695,7 +709,9 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return; } throw new CertPathValidatorException( - "Algorithm constraints check failed on keysize limits", + "Algorithm constraints check failed on keysize limits. " + + algorithm + " " + size + "bit key used with " + + cp.getCertificate().getSubjectX500Principal(), null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } @@ -722,7 +738,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return true; } - int size = KeyUtil.getKeySize(key); + size = KeyUtil.getKeySize(key); if (size == 0) { return false; // we don't allow any key of size 0. } else if (size > 0) { diff --git a/jdk/src/java.base/share/classes/sun/security/util/MessageDigestSpi2.java b/jdk/src/java.base/share/classes/sun/security/util/MessageDigestSpi2.java new file mode 100644 index 00000000000..4fbf285a8a2 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/security/util/MessageDigestSpi2.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.security.InvalidKeyException; +import javax.crypto.SecretKey; + +/** + * Special interface for additional MessageDigestSpi method(s). + */ +public interface MessageDigestSpi2 { + + /** + * Updates the digest using the specified key. + * This is used for SSL 3.0 only, we may deprecate and remove the support + * of this in the future + * + * @param key the key whose value is to be digested. + */ + void engineUpdate(SecretKey key) throws InvalidKeyException; +} diff --git a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java index 0bf5fcbe1fc..f8022c5ca94 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * 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,26 +25,49 @@ package sun.security.util; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.CodeSigner; +import java.security.CryptoPrimitive; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; import java.security.cert.CertPath; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; -import java.security.*; -import java.io.*; -import java.util.*; -import java.util.jar.*; - -import sun.security.pkcs.*; +import java.util.ArrayList; import java.util.Base64; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarException; +import java.util.jar.JarFile; +import java.util.jar.Manifest; import sun.security.jca.Providers; +import sun.security.pkcs.PKCS7; +import sun.security.pkcs.SignerInfo; public class SignatureFileVerifier { /* Are we debugging ? */ private static final Debug debug = Debug.getInstance("jar"); - /* cache of CodeSigner objects */ + private static final Set DIGEST_PRIMITIVE_SET = + Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); + + private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK = + new DisabledAlgorithmConstraints( + DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); + private ArrayList signerCache; private static final String ATTR_DIGEST = @@ -199,8 +222,15 @@ public class SignatureFileVerifier { /** get digest from cache */ - private MessageDigest getDigest(String algorithm) - { + private MessageDigest getDigest(String algorithm) throws SignatureException { + // check that algorithm is not restricted + if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, algorithm, null)) { + SignatureException e = + new SignatureException("SignatureFile check failed. " + + "Disabled algorithm used: " + algorithm); + throw e; + } + if (createdDigests == null) createdDigests = new HashMap<>(); @@ -320,7 +350,7 @@ public class SignatureFileVerifier { private boolean verifyManifestHash(Manifest sf, ManifestDigester md, List manifestDigests) - throws IOException + throws IOException, SignatureException { Attributes mattr = sf.getMainAttributes(); boolean manifestSigned = false; @@ -364,7 +394,7 @@ public class SignatureFileVerifier { private boolean verifyManifestMainAttrs(Manifest sf, ManifestDigester md) - throws IOException + throws IOException, SignatureException { Attributes mattr = sf.getMainAttributes(); boolean attrsVerified = true; @@ -430,14 +460,14 @@ public class SignatureFileVerifier { private boolean verifySection(Attributes sfAttr, String name, ManifestDigester md) - throws IOException + throws IOException, SignatureException { boolean oneDigestVerified = false; ManifestDigester.Entry mde = md.get(name,block.isOldStyle()); if (mde == null) { throw new SecurityException( - "no manifiest section for signature file entry "+name); + "no manifest section for signature file entry "+name); } if (sfAttr != null) { diff --git a/jdk/src/java.base/share/conf/net.properties b/jdk/src/java.base/share/conf/net.properties index da78a84d511..b490e174a3f 100644 --- a/jdk/src/java.base/share/conf/net.properties +++ b/jdk/src/java.base/share/conf/net.properties @@ -72,3 +72,30 @@ ftp.nonProxyHosts=localhost|127.*|[::1] # value is 10). # http.KeepAlive.remainingData=512 # http.KeepAlive.queuedConnections=10 + +# Authentication Scheme restrictions for HTTP and HTTPS. +# +# In some environments certain authentication schemes may be undesirable +# when proxying HTTP or HTTPS. For example, "Basic" results in effectively the +# cleartext transmission of the user's password over the physical network. +# This section describes the mechanism for disabling authentication schemes +# based on the scheme name. Disabled schemes will be treated as if they are not +# supported by the implementation. +# +# The 'jdk.http.auth.tunneling.disabledSchemes' property lists the authentication +# schemes that will be disabled when tunneling HTTPS over a proxy, HTTP CONNECT. +# The 'jdk.http.auth.proxying.disabledSchemes' property lists the authentication +# schemes that will be disabled when proxying HTTP. +# +# In both cases the property is a comma-separated list of, case-insensitive, +# authentication scheme names, as defined by their relevant RFCs. An +# implementation may, but is not required to, support common schemes whose names +# include: 'Basic', 'Digest', 'NTLM', 'Kerberos', 'Negotiate'. A scheme that +# is not known, or not supported, by the implementation is ignored. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. +# +#jdk.http.auth.proxying.disabledSchemes= +jdk.http.auth.tunneling.disabledSchemes=Basic + diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index df4aa8b3268..966f9ba027e 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -655,6 +655,44 @@ krb5.kdc.bad.policy = tryLast jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & denyAfter 2017-01-01, \ RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# Algorithm restrictions for signed JAR files +# +# In some environments, certain algorithms or key lengths may be undesirable +# for signed JAR validation. For example, "MD2" is generally no longer +# considered to be a secure hash algorithm. This section describes the +# mechanism for disabling algorithms based on algorithm name and/or key length. +# JARs signed with any of the disabled algorithms or key sizes will be treated +# as unsigned. +# +# The syntax of the disabled algorithm string is described as follows: +# DisabledAlgorithms: +# " DisabledAlgorithm { , DisabledAlgorithm } " +# +# DisabledAlgorithm: +# AlgorithmName [Constraint] +# +# AlgorithmName: +# (see below) +# +# Constraint: +# KeySizeConstraint +# +# KeySizeConstraint: +# keySize Operator KeyLength +# +# Operator: +# <= | < | == | != | >= | > +# +# KeyLength: +# Integer value of the algorithm's key length in bits +# +# Note: This property is currently used by the JDK Reference +# implementation. It is not guaranteed to be examined and used by other +# implementations. +# +jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024 + # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS/DTLS) processing # @@ -935,3 +973,4 @@ jdk.xml.dsig.secureValidationPolicy=\ # Otherwise, the status is UNDECIDED. # #jdk.serialFilter=pattern;pattern + diff --git a/jdk/src/java.base/share/lib/security/default.policy b/jdk/src/java.base/share/lib/security/default.policy index f57e67fb482..17e1c80e627 100644 --- a/jdk/src/java.base/share/lib/security/default.policy +++ b/jdk/src/java.base/share/lib/security/default.policy @@ -91,7 +91,6 @@ grant codeBase "jrt:/java.xml.ws" { }; grant codeBase "jrt:/jdk.charsets" { - permission java.io.FilePermission "${java.home}/-", "read"; permission java.util.PropertyPermission "os.name", "read"; permission java.util.PropertyPermission "sun.nio.cs.map", "read"; permission java.lang.RuntimePermission "charsetProvider"; @@ -104,7 +103,6 @@ grant codeBase "jrt:/jdk.crypto.ec" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.*"; permission java.lang.RuntimePermission "loadLibrary.sunec"; - permission java.util.PropertyPermission "*", "read"; permission java.security.SecurityPermission "putProviderProperty.SunEC"; permission java.security.SecurityPermission "clearProviderProperties.SunEC"; permission java.security.SecurityPermission "removeProviderProperty.SunEC"; @@ -113,11 +111,11 @@ grant codeBase "jrt:/jdk.crypto.ec" { grant codeBase "jrt:/jdk.crypto.pkcs11" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.*"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.misc"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; permission java.lang.RuntimePermission "loadLibrary.j2pkcs11"; - // needs "security.pkcs11.allowSingleThreadedModules" - permission java.util.PropertyPermission "*", "read"; + permission java.util.PropertyPermission "sun.security.pkcs11.allowSingleThreadedModules", "read"; + permission java.util.PropertyPermission "os.name", "read"; + permission java.util.PropertyPermission "os.arch", "read"; permission java.security.SecurityPermission "putProviderProperty.*"; permission java.security.SecurityPermission "clearProviderProperties.*"; permission java.security.SecurityPermission "removeProviderProperty.*"; diff --git a/jdk/src/java.base/share/native/libverify/check_code.c b/jdk/src/java.base/share/native/libverify/check_code.c index 1f9408fb206..b278f2559f7 100644 --- a/jdk/src/java.base/share/native/libverify/check_code.c +++ b/jdk/src/java.base/share/native/libverify/check_code.c @@ -1293,14 +1293,13 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial: case JVM_OPC_invokestatic: - case JVM_OPC_invokedynamic: case JVM_OPC_invokeinterface: { /* Make sure the constant pool item is the right type. */ int key = (code[offset + 1] << 8) + code[offset + 2]; const char *methodname; jclass cb = context->class; fullinfo_type clazz_info; - int is_constructor, is_internal, is_invokedynamic; + int is_constructor, is_internal; int kind; switch (opcode ) { @@ -1309,9 +1308,6 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) ? (1 << JVM_CONSTANT_Methodref) : ((1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref))); break; - case JVM_OPC_invokedynamic: - kind = 1 << JVM_CONSTANT_NameAndType; - break; case JVM_OPC_invokeinterface: kind = 1 << JVM_CONSTANT_InterfaceMethodref; break; @@ -1319,7 +1315,6 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) kind = 1 << JVM_CONSTANT_Methodref; } - is_invokedynamic = opcode == JVM_OPC_invokedynamic; /* Make sure the constant pool item is the right type. */ verify_constant_pool_type(context, key, kind); methodname = JVM_GetCPMethodNameUTF(env, cb, key); @@ -1328,11 +1323,8 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) is_internal = methodname[0] == '<'; pop_and_free(context); - if (is_invokedynamic) - clazz_info = context->object_info; // anything will do - else - clazz_info = cp_index_to_class_fullinfo(context, key, - JVM_CONSTANT_Methodref); + clazz_info = cp_index_to_class_fullinfo(context, key, + JVM_CONSTANT_Methodref); this_idata->operand.i = key; this_idata->operand2.fi = clazz_info; if (is_constructor) { @@ -1387,17 +1379,15 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) "Fourth operand byte of invokeinterface must be zero"); } pop_and_free(context); - } else if (opcode == JVM_OPC_invokedynamic) { - if (code[offset + 3] != 0 || code[offset + 4] != 0) { - CCerror(context, - "Third and fourth operand bytes of invokedynamic must be zero"); - } } else if (opcode == JVM_OPC_invokevirtual || opcode == JVM_OPC_invokespecial) set_protected(context, inumber, key, opcode); break; } + case JVM_OPC_invokedynamic: + CCerror(context, + "invokedynamic bytecode is not supported in this class file version"); case JVM_OPC_instanceof: case JVM_OPC_checkcast: @@ -2085,7 +2075,6 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial: case JVM_OPC_invokeinit: /* invokespecial call to */ - case JVM_OPC_invokedynamic: case JVM_OPC_invokestatic: case JVM_OPC_invokeinterface: { /* The top stuff on the stack depends on the method signature */ int operand = this_idata->operand.i; @@ -2101,8 +2090,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac print_formatted_methodname(context, operand); } #endif - if (opcode != JVM_OPC_invokestatic && - opcode != JVM_OPC_invokedynamic) + if (opcode != JVM_OPC_invokestatic) /* First, push the object */ *ip++ = (opcode == JVM_OPC_invokeinit ? '@' : 'A'); for (p = signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) { @@ -2388,7 +2376,6 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial: case JVM_OPC_invokeinit: - case JVM_OPC_invokedynamic: case JVM_OPC_invokeinterface: case JVM_OPC_invokestatic: { int operand = this_idata->operand.i; const char *signature = @@ -2398,8 +2385,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac int item; const char *p; check_and_push(context, signature, VM_STRING_UTF); - if (opcode == JVM_OPC_invokestatic || - opcode == JVM_OPC_invokedynamic) { + if (opcode == JVM_OPC_invokestatic) { item = 0; } else if (opcode == JVM_OPC_invokeinit) { fullinfo_type init_type = this_idata->operand2.fi; @@ -2795,7 +2781,6 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial: case JVM_OPC_invokeinit: - case JVM_OPC_invokedynamic: case JVM_OPC_invokestatic: case JVM_OPC_invokeinterface: { /* Look to signature to determine correct result. */ int operand = this_idata->operand.i; diff --git a/jdk/src/java.base/solaris/lib/security/default.policy b/jdk/src/java.base/solaris/lib/security/default.policy index 4f36083b634..73c2b948c32 100644 --- a/jdk/src/java.base/solaris/lib/security/default.policy +++ b/jdk/src/java.base/solaris/lib/security/default.policy @@ -4,7 +4,10 @@ grant codeBase "jrt:/jdk.crypto.ucrypto" { permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; permission java.lang.RuntimePermission "loadLibrary.j2ucrypto"; // need "com.oracle.security.ucrypto.debug" for debugging - permission java.util.PropertyPermission "*", "read"; + permission java.util.PropertyPermission "com.oracle.security.ucrypto.debug", "read"; + permission java.util.PropertyPermission "file.separator", "read"; + permission java.util.PropertyPermission "java.home", "read"; + permission java.util.PropertyPermission "os.name", "read"; permission java.security.SecurityPermission "putProviderProperty.OracleUcrypto"; permission java.security.SecurityPermission diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.c b/jdk/src/java.base/unix/native/libnet/net_util_md.c index 4fe4950c362..13b97dcbc9a 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.c +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c @@ -273,13 +273,10 @@ int cmpScopeID (unsigned int scope, struct sockaddr *him) { #endif - void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, const char *defaultDetail) { - char errmsg[255]; - sprintf(errmsg, "errno: %d, error: %s\n", errno, defaultDetail); - JNU_ThrowByNameWithLastError(env, name, errmsg); + JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail); } void diff --git a/jdk/src/java.base/windows/native/libjli/java_md.c b/jdk/src/java.base/windows/native/libjli/java_md.c index 3d29357542b..1db3c408740 100644 --- a/jdk/src/java.base/windows/native/libjli/java_md.c +++ b/jdk/src/java.base/windows/native/libjli/java_md.c @@ -48,6 +48,10 @@ static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, char *jvmpath, jint jvmpathsize); static jboolean GetJREPath(char *path, jint pathsize); +#ifdef USE_REGISTRY_LOOKUP +jboolean GetPublicJREHome(char *buf, jint bufsize); +#endif + /* We supports warmup for UI stack that is performed in parallel * to VM initialization. * This helps to improve startup of UI application as warmup phase @@ -346,6 +350,14 @@ GetJREPath(char *path, jint pathsize) } } +#ifdef USE_REGISTRY_LOOKUP + /* Lookup public JRE using Windows registry. */ + if (GetPublicJREHome(path, pathsize)) { + JLI_TraceLauncher("JRE path is %s\n", path); + return JNI_TRUE; + } +#endif + JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL); return JNI_FALSE; } diff --git a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c index c7f512f2cc2..0f0fbe19712 100644 --- a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c +++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c @@ -554,14 +554,20 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) * Create a NetworkInterface object and populate it */ netifObj = (*env)->NewObject(env, ni_class, ni_ctor); + if (netifObj == NULL) { + return NULL; + } name = (*env)->NewStringUTF(env, ifs->name); + if (name == NULL) { + return NULL; + } if (ifs->dNameIsUnicode) { displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, (jsize)wcslen ((PWCHAR)ifs->displayName)); } else { displayName = (*env)->NewStringUTF(env, ifs->displayName); } - if (netifObj == NULL || name == NULL || displayName == NULL) { + if (displayName == NULL) { return NULL; } (*env)->SetObjectField(env, netifObj, ni_nameID, name); @@ -621,26 +627,28 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); } else /* AF_INET6 */ { int scope; + jboolean ret; iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); - if (iaObj) { - jboolean ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr)); - if (ret == JNI_FALSE) { - return NULL; - } - scope = addrs->addr.sa6.sin6_scope_id; - if (scope != 0) { /* zero is default value, no need to set */ - setInet6Address_scopeid(env, iaObj, scope); - setInet6Address_scopeifname(env, iaObj, netifObj); - } - ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); - if (ibObj == NULL) { - free_netaddr(netaddrP); - return NULL; - } - (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); - (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); - (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); + if (iaObj == NULL) { + return NULL; } + ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr)); + if (ret == JNI_FALSE) { + return NULL; + } + scope = addrs->addr.sa6.sin6_scope_id; + if (scope != 0) { /* zero is default value, no need to set */ + setInet6Address_scopeid(env, iaObj, scope); + setInet6Address_scopeifname(env, iaObj, netifObj); + } + ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); + if (ibObj == NULL) { + free_netaddr(netaddrP); + return NULL; + } + (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); + (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); + (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); } (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); addrs = addrs->next; diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c index aff81a69720..a01c46b36fd 100644 --- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c +++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c @@ -830,6 +830,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, } if (IS_NULL(addressObj)) { JNU_ThrowNullPointerException(env, "Null address in peek()"); + return -1; } else { address = getInetAddress_addr(env, addressObj); /* We only handle IPv4 for now. Will support IPv6 once its in the os */ @@ -1127,11 +1128,23 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi } if (n == -1) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; } else if (n == -2) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; } else if (n < 0) { NET_ThrowCurrent(env, "Datagram receive failed"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; } else { jobject packetAddress; @@ -1882,7 +1895,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption default : JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket option not supported by PlainDatagramSocketImp"); - break; + return; } @@ -2325,6 +2338,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobjec if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl, sizeof (ittl)) < 0) { NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); + return; } } @@ -2518,6 +2532,9 @@ static void mcast_join_leave(JNIEnv *env, jobject this, } else { ifindex = getIndexFromIf (env, niObj); if (ifindex == -1) { + if ((*env)->ExceptionOccurred(env)) { + return; + } NET_ThrowCurrent(env, "get ifindex failed"); return; } diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c index aea3c351214..51e33a5b464 100644 --- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c +++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c @@ -108,7 +108,7 @@ Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) { psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); CHECK_NULL(psi_portID); psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); - CHECK_NULL(psi_portID); + CHECK_NULL(psi_lastfdID); psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); CHECK_NULL(psi_localportID); psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); @@ -153,17 +153,17 @@ Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this, fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); if (IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "null fd1 object"); (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); NET_SocketClose(fd); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "null fd1 object"); return; } fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); if (fd1 == -1) { - NET_ThrowCurrent(env, "create"); (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); NET_SocketClose(fd); + NET_ThrowCurrent(env, "create"); return; } else { /* Set socket attribute so it is not passed to any child process */ @@ -907,6 +907,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption isRcvTimeoutSupported = JNI_FALSE; } else { NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); + return; } } if (fd1 != -1) { diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c index 523ea18523d..0afbe08b881 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.c +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c @@ -205,9 +205,7 @@ NET_ThrowCurrent(JNIEnv *env, char *msg) void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, const char *defaultDetail) { - char errmsg[255]; - sprintf(errmsg, "errno: %d, error: %s\n", WSAGetLastError(), defaultDetail); - JNU_ThrowByNameWithLastError(env, name, errmsg); + JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail); } jfieldID diff --git a/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c b/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c index 0e03e6e34c2..821ad9eeded 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c +++ b/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c @@ -202,6 +202,7 @@ Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { JNU_ThrowIOExceptionWithLastError(env, "Write failed"); + return IOS_THROWN; } return convertReturnVal(env, (jint)written, JNI_FALSE); @@ -250,6 +251,7 @@ Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fd if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { JNU_ThrowIOExceptionWithLastError(env, "Write failed"); + return IOS_THROWN; } return convertLongReturnVal(env, totalWritten, JNI_FALSE); diff --git a/jdk/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp b/jdk/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp index 40cddfcf53d..cadbb11bc15 100644 --- a/jdk/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp +++ b/jdk/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_PCM.cpp @@ -817,6 +817,10 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, ERROR1("<() { public ClassLoader run() { @@ -156,12 +146,12 @@ class AppletSecurity extends AWTSecurityManager { ProtectionDomain[] pds = null; try { - acc = (AccessControlContext) facc.get(currentLoader); + acc = JNUCLA.getAccessControlContext(ld); if (acc == null) { return null; } - pds = (ProtectionDomain[]) fcontext.get(acc); + pds = JSA.getProtectDomains(acc); if (pds == null) { return null; } diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.cpp index 63f7b644fec..9b92060d9e5 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.cpp @@ -46,6 +46,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor) ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const LEReferenceTo &morphSubtableHeader, LEErrorCode &success) : StateTableProcessor(morphSubtableHeader, success), entryTable(), contextualGlyphSubstitutionHeader(morphSubtableHeader, success) { + if (LE_FAILURE(success)) return; contextualGlyphSubstitutionHeader.orphan(); substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset); @@ -66,10 +67,10 @@ void ContextualGlyphSubstitutionProcessor::beginStateTable() markGlyph = 0; } -ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) +ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success) { - LEErrorCode success = LE_NO_ERROR; const ContextualGlyphSubstitutionStateEntry *entry = entryTable.getAlias(index, success); + if (LE_FAILURE(success)) return 0; ByteOffset newState = SWAPW(entry->newStateOffset); le_int16 flags = SWAPW(entry->flags); WordOffset markOffset = SWAPW(entry->markOffset); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.h b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.h index 136398f7661..7cf15323089 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.h +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualGlyphSubstProc.h @@ -52,7 +52,7 @@ class ContextualGlyphSubstitutionProcessor : public StateTableProcessor public: virtual void beginStateTable(); - virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index); + virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success); virtual void endStateTable(); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.cpp index 5598349131a..512ec4d527e 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.cpp @@ -63,10 +63,10 @@ void IndicRearrangementProcessor::beginStateTable() lastGlyph = 0; } -ByteOffset IndicRearrangementProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) +ByteOffset IndicRearrangementProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success) { - LEErrorCode success = LE_NO_ERROR; // todo- make a param? - const IndicRearrangementStateEntry *entry = entryTable.getAlias(index,success); + const IndicRearrangementStateEntry *entry = entryTable.getAlias(index, success); + if (LE_FAILURE(success)) return 0; ByteOffset newState = SWAPW(entry->newStateOffset); IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.h b/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.h index 42d7a249aa1..593c3188904 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.h +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/IndicRearrangementProcessor.h @@ -52,7 +52,7 @@ class IndicRearrangementProcessor : public StateTableProcessor public: virtual void beginStateTable(); - virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index); + virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success); virtual void endStateTable(); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp index 76131fd2193..111346224e4 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp @@ -67,9 +67,8 @@ void LigatureSubstitutionProcessor::beginStateTable() m = -1; } -ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) +ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success) { - LEErrorCode success = LE_NO_ERROR; const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success); if (LE_FAILURE(success)) { currGlyph++; diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.h b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.h index 1765a71d674..67bab99a1eb 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.h +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.h @@ -54,7 +54,7 @@ class LigatureSubstitutionProcessor : public StateTableProcessor public: virtual void beginStateTable(); - virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index); + virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success); virtual void endStateTable(); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.cpp index f5bef5f3038..2234faf704b 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.cpp @@ -81,6 +81,7 @@ void StateTableProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &suc while (currGlyph <= glyphCount) { if(LE_STATE_PATIENCE_DECR()) break; // patience exceeded. + if (LE_FAILURE(success)) break; ClassCode classCode = classCodeOOB; if (currGlyph == glyphCount) { // XXX: How do we handle EOT vs. EOL? @@ -100,7 +101,7 @@ void StateTableProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &suc EntryTableIndex entryTableIndex = stateArray.getObject((le_uint8)classCode, success); if (LE_FAILURE(success)) { break; } LE_STATE_PATIENCE_CURR(le_int32, currGlyph); - currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); + currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); LE_STATE_PATIENCE_INCR(currGlyph); } diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.h b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.h index 2e8d7f606b5..e437da73f72 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.h +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor.h @@ -53,7 +53,7 @@ public: virtual void beginStateTable() = 0; - virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) = 0; + virtual ByteOffset processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index, LEErrorCode &success) = 0; virtual void endStateTable() = 0; diff --git a/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c b/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c index dbe8b45eb62..aa96cbb440b 100644 --- a/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c +++ b/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c @@ -244,7 +244,7 @@ void LinLerp1D(register const cmsUInt16Number Value[], // To prevent out of bounds indexing cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) { - return v < 0.0f ? 0.0f : (v > 1.0f ? 1.0f : v); + return v < 0.0f || v != v ? 0.0f : (v > 1.0f ? 1.0f : v); } // Floating-point version of 1D interpolation diff --git a/jdk/src/java.desktop/share/native/liblcms/cmsio0.c b/jdk/src/java.desktop/share/native/liblcms/cmsio0.c index 9e982aecf69..f86f2e738d8 100644 --- a/jdk/src/java.desktop/share/native/liblcms/cmsio0.c +++ b/jdk/src/java.desktop/share/native/liblcms/cmsio0.c @@ -1543,6 +1543,13 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) // If the element is already in memory, return the pointer if (Icc -> TagPtrs[n]) { + if (Icc -> TagTypeHandlers[n] == NULL) goto Error; + BaseType = Icc -> TagTypeHandlers[n]->Signature; + if (BaseType == 0) goto Error; + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); + if (TagDescriptor == NULL) goto Error; + if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; + if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); diff --git a/jdk/src/java.desktop/share/native/liblcms/cmstypes.c b/jdk/src/java.desktop/share/native/liblcms/cmstypes.c index 2563a62cc96..3f8999f23f6 100644 --- a/jdk/src/java.desktop/share/native/liblcms/cmstypes.c +++ b/jdk/src/java.desktop/share/native/liblcms/cmstypes.c @@ -4313,7 +4313,10 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans; - for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i]; + for (i=0; i < nMaxGrids; i++) { + if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least + GridPoints[i] = (cmsUInt32Number)Dimensions8[i]; + } // Allocate the true CLUT mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL); diff --git a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceDataProxy.java b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceDataProxy.java index fd29ac38ba2..6f21c01daeb 100644 --- a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceDataProxy.java +++ b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/X11SurfaceDataProxy.java @@ -102,10 +102,13 @@ public abstract class X11SurfaceDataProxy extends SurfaceDataProxy int w, int h) { if (cachedData == null) { - // Bitmask will be created lazily during the blit phase - cachedData = X11SurfaceData.createData(x11gc, w, h, - x11gc.getColorModel(), - null, 0, getTransparency()); + try { + // Bitmask will be created lazily during the blit phase + cachedData = X11SurfaceData.createData(x11gc, w, h, + x11gc.getColorModel(), + null, 0, getTransparency()); + } catch (OutOfMemoryError oome) { + } } return cachedData; } diff --git a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRPMBlitLoops.java b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRPMBlitLoops.java index 2cfd8c2a456..3704367a9f2 100644 --- a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRPMBlitLoops.java +++ b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRPMBlitLoops.java @@ -138,6 +138,9 @@ public class XRPMBlitLoops { vImg = (SunVolatileImage) dst.getGraphicsConfig().createCompatibleVolatileImage(w, h, src.getTransparency()); vImg.setAccelerationPriority(1.0f); + if (!(vImg.getDestSurface() instanceof XRSurfaceData)) { + throw new InvalidPipeException("Could not create XRSurfaceData"); + } if (src.getTransparency() == SurfaceData.OPAQUE) { rgbTmpPM = new WeakReference(vImg); } else { diff --git a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceDataProxy.java b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceDataProxy.java index ddc621a3f5e..2c82e30197e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceDataProxy.java +++ b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceDataProxy.java @@ -59,9 +59,12 @@ public class XRSurfaceDataProxy extends SurfaceDataProxy implements Transparency public SurfaceData validateSurfaceData(SurfaceData srcData, SurfaceData cachedData, int w, int h) { if (cachedData == null) { - cachedData = XRSurfaceData.createData(xrgc, w, h, - xrgc.getColorModel(), null, 0, - getTransparency(), true); + try { + cachedData = XRSurfaceData.createData(xrgc, w, h, + xrgc.getColorModel(), null, 0, + getTransparency(), true); + } catch (OutOfMemoryError oome) { + } } return cachedData; } diff --git a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c index 07c13f7b7e1..0fe12d553da 100644 --- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c +++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c @@ -441,7 +441,7 @@ jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width * width , height must be nonzero otherwise XCreatePixmap * generates BadValue in error_handler */ - if (width <= 0 || height <= 0) { + if (width <= 0 || height <= 0 || width > 32767 || height > 32767) { JNU_ThrowOutOfMemoryError(env, "Can't create offscreen surface"); return JNI_FALSE; diff --git a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCM.c b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCM.c index 9046841831a..506e002fce4 100644 --- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCM.c +++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCM.c @@ -434,7 +434,10 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0); } #endif - + if (channels <= 0) { + ERROR1("ERROR: Invalid number of channels=%d!\n", channels); + return NULL; + } info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo)); if (!info) { ERROR0("Out of memory\n"); diff --git a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c index fdd5b94facc..332abb58b6f 100644 --- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c +++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c @@ -434,7 +434,10 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0); } #endif - + if (channels <= 0) { + ERROR1("ERROR: Invalid number of channels=%d!\n", channels); + return NULL; + } info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo)); if (!info) { ERROR0("Out of memory\n"); diff --git a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c index cb428920d1f..3d5682b433c 100644 --- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c +++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c @@ -182,6 +182,10 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding); return NULL; } + if (channels <= 0) { + ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels); + return NULL; + } info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo)); if (!info) { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java index b60fb0b082b..36dcc87011d 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,6 +153,19 @@ class WFramePeer extends WWindowPeer implements FramePeer { @Override public void setMenuBar(MenuBar mb) { WMenuBarPeer mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); + if (mbPeer != null) { + if (mbPeer.framePeer != this) { + mb.removeNotify(); + mb.addNotify(); + mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); + if (mbPeer != null && mbPeer.framePeer != this) { + throw new IllegalStateException("Wrong parent peer"); + } + } + if (mbPeer != null) { + addChildPeer(mbPeer); + } + } setMenuBar0(mbPeer); updateInsets(insets_); } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuBarPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuBarPeer.java index 3a661da6a3a..9c68e715192 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuBarPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuBarPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ final class WMenuBarPeer extends WMenuPeer implements MenuBarPeer { // MenuBarPeer implementation + final WFramePeer framePeer; + @Override public native void addMenu(Menu m); @Override @@ -44,8 +46,11 @@ final class WMenuBarPeer extends WMenuPeer implements MenuBarPeer { // Toolkit & peer internals WMenuBarPeer(MenuBar target) { this.target = target; - WFramePeer framePeer = (WFramePeer) + framePeer = (WFramePeer) WToolkit.targetToPeer(target.getParent()); + if (framePeer != null) { + framePeer.addChildPeer(this); + } create(framePeer); // fix for 5088782: check if menu object is created successfully checkMenuCreation(); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java index 9f681e76fbd..5a581193b8d 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,7 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { this.target = target; this.parent = (WMenuPeer) WToolkit.targetToPeer(target.getParent()); this.isCheckbox = isCheckbox; + parent.addChildPeer(this); create(parent); // fix for 5088782: check if menu object is created successfully checkMenuCreation(); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuPeer.java index 567af925d38..9272a48bac5 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMenuPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,10 +51,12 @@ class WMenuPeer extends WMenuItemPeer implements MenuPeer { if (parent instanceof MenuBar) { WMenuBarPeer mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(parent); this.parent = mbPeer; + mbPeer.addChildPeer(this); createMenu(mbPeer); } else if (parent instanceof Menu) { this.parent = (WMenuPeer) WToolkit.targetToPeer(parent); + this.parent.addChildPeer(this); createSubMenu(this.parent); } else { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java index c456df27dd9..b5324076486 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,9 @@ */ package sun.awt.windows; +import java.util.Map; +import java.util.WeakHashMap; + abstract class WObjectPeer { static { @@ -45,6 +48,8 @@ abstract class WObjectPeer { // used to synchronize the state of this peer private final Object stateLock = new Object(); + private volatile Map childPeers; + public static WObjectPeer getPeerForTarget(Object t) { WObjectPeer peer = (WObjectPeer) WToolkit.targetToPeer(t); return peer; @@ -77,6 +82,9 @@ abstract class WObjectPeer { } if (call_disposeImpl) { + if (childPeers != null) { + disposeChildPeers(); + } disposeImpl(); } } @@ -88,4 +96,33 @@ abstract class WObjectPeer { * Initialize JNI field and method IDs */ private static native void initIDs(); + + // if a child peer existence depends on this peer, add it to this collection + final void addChildPeer(WObjectPeer child) { + synchronized (getStateLock()) { + if (childPeers == null) { + childPeers = new WeakHashMap<>(); + } + if (isDisposed()) { + throw new IllegalStateException("Parent peer is disposed"); + } + childPeers.put(child, this); + } + } + + // called to dispose dependent child peers + private void disposeChildPeers() { + synchronized (getStateLock()) { + for (WObjectPeer child : childPeers.keySet()) { + if (child != null) { + try { + child.dispose(); + } + catch (Exception e) { + // ignored + } + } + } + } + } } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java index 6818be35dba..d37858dff6b 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ final class WPopupMenuPeer extends WMenuPeer implements PopupMenuPeer { parent = WToolkit.getNativeContainer((Component)parent); parentPeer = (WComponentPeer) WToolkit.targetToPeer(parent); } + parentPeer.addChildPeer(this); createMenu(parentPeer); // fix for 5088782: check if menu object is created successfully checkMenuCreation(); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp index 2e7c77952e4..b7e63628c2a 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp @@ -640,7 +640,7 @@ SIZE AwtFont::TextSize(AwtFont* font, int columns, int rows) int AwtFont::getFontDescriptorNumber(JNIEnv *env, jobject font, jobject fontDescriptor) { - int i, num; + int i, num = 0; jobject refFontDescriptor; jobjectArray array; diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index fd7c0899e15..6c8d65a47c7 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1113,11 +1113,19 @@ AwtMenuBar* AwtFrame::GetMenuBar() void AwtFrame::SetMenuBar(AwtMenuBar* mb) { + if (menuBar) { + menuBar->SetFrame(NULL); + } menuBar = mb; if (mb == NULL) { // Remove existing menu bar, if any. ::SetMenu(GetHWnd(), NULL); } else { + AwtFrame* oldFrame = menuBar->GetFrame(); + if (oldFrame && oldFrame != this) { + oldFrame->SetMenuBar(NULL); + } + menuBar->SetFrame(this); if (menuBar->GetHMenu() != NULL) { ::SetMenu(GetHWnd(), menuBar->GetHMenu()); } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp index d15e2809a73..b62775f8b1b 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,9 @@ AwtMenuBar::~AwtMenuBar() void AwtMenuBar::Dispose() { + if (m_frame != NULL && m_frame->GetMenuBar() == this) { + m_frame->SetMenuBar(NULL); + } m_frame = NULL; AwtMenu::Dispose(); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.h index b4291f17a60..797cf0a58bd 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,9 @@ public: virtual AwtMenuBar* GetMenuBar() { return this; } INLINE AwtFrame* GetFrame() { return m_frame; } + INLINE void SetFrame(AwtFrame* frame) { + m_frame = frame; + } virtual HWND GetOwnerHWnd(); virtual void RedrawMenuBar(); diff --git a/jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp b/jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp index ce19bbaa810..d8db5d7480b 100644 --- a/jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp +++ b/jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp @@ -859,6 +859,10 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, ERROR1("DAUDIO_Open: ERROR: cannot open the device with encoding=%d!\n", encoding); return NULL; } + if (channels <= 0) { + ERROR1("DAUDIO_Open: ERROR: Invalid number of channels=%d!\n", channels); + return NULL; + } if (sampleSizeInBits > 8 && #ifdef _LITTLE_ENDIAN isBigEndian diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java index 9433bf891e7..a5d337ff1d2 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java @@ -39,8 +39,9 @@ public class ClassLoaderWithRepository extends ClassLoader { } protected Class findClass(String name) throws ClassNotFoundException { + Class cls; try { - return repository.loadClass(name); + cls = repository.loadClass(name); } catch (ClassNotFoundException cne) { if (cl2 != null) { return cl2.loadClass(name); @@ -48,6 +49,15 @@ public class ClassLoaderWithRepository extends ClassLoader { throw cne; } } + + if(!cls.getName().equals(name)){ + if (cl2 != null) { + return cl2.loadClass(name); + } else { + throw new ClassNotFoundException(name); + } + } + return cls; } private ClassLoaderRepository repository; diff --git a/jdk/src/java.scripting/share/classes/javax/script/ScriptContext.java b/jdk/src/java.scripting/share/classes/javax/script/ScriptContext.java index c283a39d3d7..5c7456faab8 100644 --- a/jdk/src/java.scripting/share/classes/javax/script/ScriptContext.java +++ b/jdk/src/java.scripting/share/classes/javax/script/ScriptContext.java @@ -85,7 +85,8 @@ public interface ScriptContext { public Bindings getBindings(int scope); /** - * Sets the value of an attribute in a given scope. + * Sets the value of an attribute in a given scope. If the scope is GLOBAL_SCOPE + * and no Bindings is set for GLOBAL_SCOPE, then setAttribute call is a no-op. * * @param name The name of the attribute to set * @param value The value of the attribute diff --git a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java index 6536c4e6e31..27c70ef2dfe 100644 --- a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java +++ b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java @@ -216,8 +216,9 @@ public interface ScriptEngineFactory { * @param statements The statements to be executed. May be return values of * calls to the getMethodCallSyntax and getOutputStatement methods. * @return The Program + * + * @throws NullPointerException if the statements array or any of its elements is null */ - public String getProgram(String... statements); /** diff --git a/jdk/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java b/jdk/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java index c56ce7adb8c..119b3f26fb3 100644 --- a/jdk/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java +++ b/jdk/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java @@ -213,7 +213,8 @@ public class SimpleScriptContext implements ScriptContext { } /** - * Sets the value of an attribute in a given scope. + * Sets the value of an attribute in a given scope. If the scope is GLOBAL_SCOPE + * and no Bindings is set for GLOBAL_SCOPE, then setAttribute call is a no-op. * * @param name The name of the attribute to set * @param value The value of the attribute diff --git a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java index c220ca1b362..9fb9055ab67 100644 --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java @@ -694,7 +694,7 @@ public class KerberosTicket implements Destroyable, Refreshable, "Proxy Ticket " + flags[PROXY_TICKET_FLAG] + "\n" + "Postdated Ticket " + flags[POSTDATED_TICKET_FLAG] + "\n" + "Renewable Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" + - "Initial Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" + + "Initial Ticket " + flags[INITIAL_TICKET_FLAG] + "\n" + "Auth Time = " + String.valueOf(authTime) + "\n" + "Start Time = " + String.valueOf(startTime) + "\n" + "End Time = " + endTime.toString() + "\n" + diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java index de822922b36..37dd499e727 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java @@ -376,14 +376,14 @@ public class Base64 { return null; } - int lengthDataBits = binaryData.length * EIGHTBIT; - if (lengthDataBits == 0) { + long lengthDataBits = ((long) binaryData.length) * ((long) EIGHTBIT); + if (lengthDataBits == 0L) { return ""; } - int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; - int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; - int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; + long fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = (int) (lengthDataBits / TWENTYFOURBITGROUP); + int numberQuartet = fewerThan24bits != 0L ? numberTriplets + 1 : numberTriplets; int quartesPerLine = length / 4; int numberLines = (numberQuartet - 1) / quartesPerLine; char encodedData[] = null; diff --git a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp index 44c3f1a8c44..570b3740b8b 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp +++ b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #define OID_EKU_ANY "2.5.29.37.0" @@ -48,6 +49,7 @@ #define KEYSTORE_EXCEPTION "java/security/KeyStoreException" #define PROVIDER_EXCEPTION "java/security/ProviderException" #define SIGNATURE_EXCEPTION "java/security/SignatureException" +#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError" extern "C" { @@ -56,11 +58,23 @@ extern "C" { */ DEF_STATIC_JNI_OnLoad +/* + * Throws an arbitrary Java exception with the given message. + */ +void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName, + const char *szMessage) +{ + jclass exceptionClazz = env->FindClass(exceptionName); + if (exceptionClazz != NULL) { + env->ThrowNew(exceptionClazz, szMessage); + } +} + /* * Throws an arbitrary Java exception. * The exception message is a Windows system error message. */ -void ThrowException(JNIEnv *env, char *exceptionName, DWORD dwError) +void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError) { char szMessage[1024]; szMessage[0] = '\0'; @@ -71,12 +85,22 @@ void ThrowException(JNIEnv *env, char *exceptionName, DWORD dwError) strcpy(szMessage, "Unknown error"); } - jclass exceptionClazz = env->FindClass(exceptionName); - if (exceptionClazz != NULL) { - env->ThrowNew(exceptionClazz, szMessage); - } + ThrowExceptionWithMessage(env, exceptionName, szMessage); } +/* + * Overloaded 'operator new[]' variant, which will raise Java's + * OutOfMemoryError in the case of a failure. + */ +static void* operator new[](std::size_t size, JNIEnv *env) +{ + void* buf = ::operator new[](size, std::nothrow); + if (buf == NULL) { + ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR, + "Native memory allocation failed"); + } + return buf; +} /* * Maps the name of a hash algorithm to an algorithm identifier. @@ -211,7 +235,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed } else if (length > 0) { - pbData = new BYTE[length]; + pbData = new (env) BYTE[length]; + if (pbData == NULL) { + __leave; + } if (::CryptGenRandom( hCryptProv, @@ -441,7 +468,11 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateCh NULL, 0)) > 1) { // Found friendly name - pszNameString = new char[cchNameString]; + pszNameString = new (env) char[cchNameString]; + if (pszNameString == NULL) { + __leave; + } + CertGetNameString(pc, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString); @@ -578,7 +609,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_signHash } // Copy hash from Java to native buffer - pHashBuffer = new jbyte[jHashSize]; + pHashBuffer = new (env) jbyte[jHashSize]; + if (pHashBuffer == NULL) { + __leave; + } env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer); // Set hash value in the hash object @@ -616,7 +650,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_signHash __leave; } - pSignedHashBuffer = new jbyte[dwBufLen]; + pSignedHashBuffer = new (env) jbyte[dwBufLen]; + if (pSignedHashBuffer == NULL) { + __leave; + } if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) { ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); @@ -704,9 +741,16 @@ JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_RSASignature_verifySignedHas } // Copy hash and signedHash from Java to native buffer - pHashBuffer = new jbyte[jHashSize]; + pHashBuffer = new (env) jbyte[jHashSize]; + if (pHashBuffer == NULL) { + __leave; + } env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer); - pSignedHashBuffer = new jbyte[jSignedHashSize]; + + pSignedHashBuffer = new (env) jbyte[jSignedHashSize]; + if (pSignedHashBuffer == NULL) { + __leave; + } env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize, pSignedHashBuffer); @@ -919,7 +963,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate } // Copy encoding from Java to native buffer - pbCertEncoding = new jbyte[jCertEncodingSize]; + pbCertEncoding = new (env) jbyte[jCertEncodingSize]; + if (pbCertEncoding == NULL) { + __leave; + } env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding); // Create a certificate context from the encoded cert @@ -932,7 +979,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate // Set the certificate's friendly name int size = env->GetStringLength(jCertAliasName); - pszCertAliasName = new WCHAR[size + 1]; + pszCertAliasName = new (env) WCHAR[size + 1]; + if (pszCertAliasName == NULL) { + __leave; + } jCertAliasChars = env->GetStringChars(jCertAliasName, NULL); memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR)); @@ -970,7 +1020,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate __leave; } - pszContainerName = new char[dwDataLen]; + pszContainerName = new (env) char[dwDataLen]; + if (pszContainerName == NULL) { + __leave; + } if (! ::CryptGetProvParam( (HCRYPTPROV) hCryptProv, @@ -984,7 +1037,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate } // Convert to a wide char string - pwszContainerName = new WCHAR[dwDataLen]; + pwszContainerName = new (env) WCHAR[dwDataLen]; + if (pwszContainerName == NULL) { + __leave; + } if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) { ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); @@ -1007,7 +1063,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate __leave; } - pszProviderName = new char[dwDataLen]; + pszProviderName = new (env) char[dwDataLen]; + if (pszProviderName == NULL) { + __leave; + } if (! ::CryptGetProvParam( (HCRYPTPROV) hCryptProv, @@ -1021,7 +1080,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate } // Convert to a wide char string - pwszProviderName = new WCHAR[dwDataLen]; + pwszProviderName = new (env) WCHAR[dwDataLen]; + if (pwszProviderName == NULL) { + __leave; + } if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) { ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); @@ -1161,7 +1223,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate } // Copy encoding from Java to native buffer - pbCertEncoding = new jbyte[jCertEncodingSize]; + pbCertEncoding = new (env) jbyte[jCertEncodingSize]; + if (pbCertEncoding == NULL) { + __leave; + } env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding); // Create a certificate context from the encoded cert @@ -1184,7 +1249,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate if ((cchNameString = ::CertGetNameString(pTBDCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) { - pszNameString = new char[cchNameString]; + pszNameString = new (env) char[cchNameString]; + if (pszNameString == NULL) { + __leave; + } ::CertGetNameString(pTBDCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString, @@ -1334,7 +1402,10 @@ JNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_findCertificateUsingA continue; // not found } - pszNameString = new char[cchNameString]; + pszNameString = new (env) char[cchNameString]; + if (pszNameString == NULL) { + __leave; + } if (::CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString, @@ -1510,7 +1581,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSACipher_encryptDecrypt __try { // Copy data from Java buffer to native buffer - pData = new jbyte[dwBufLen]; + pData = new (env) jbyte[dwBufLen]; + if (pData == NULL) { + __leave; + } env->GetByteArrayRegion(jData, 0, dwBufLen, pData); if (doEncrypt == JNI_TRUE) { @@ -1584,7 +1658,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyB __leave; } - pbKeyBlob = new BYTE[dwBlobLen]; + pbKeyBlob = new (env) BYTE[dwBlobLen]; + if (pbKeyBlob == NULL) { + __leave; + } // Generate key blob if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, @@ -1638,8 +1715,12 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent RSAPUBKEY* pRsaPubKey = (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC)); + int len = sizeof(pRsaPubKey->pubexp); - exponentBytes = new jbyte[len]; + exponentBytes = new (env) jbyte[len]; + if (exponentBytes == NULL) { + __leave; + } // convert from little-endian while copying from blob for (int i = 0, j = len - 1; i < len; i++, j--) { @@ -1690,9 +1771,12 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus RSAPUBKEY* pRsaPubKey = (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC)); - int len = pRsaPubKey->bitlen / 8; - modulusBytes = new jbyte[len]; + int len = pRsaPubKey->bitlen / 8; + modulusBytes = new (env) jbyte[len]; + if (modulusBytes == NULL) { + __leave; + } BYTE * pbModulus = (BYTE *) (keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); @@ -1813,12 +1897,16 @@ jbyteArray generateKeyBlob( (jKeyBitLength / 8); } - jbyte* jBlobBytes = new jbyte[jBlobLength]; + jbyte* jBlobBytes = NULL; jbyte* jBlobElement; jbyteArray jBlob = NULL; jsize jElementLength; __try { + jBlobBytes = new (env) jbyte[jBlobLength]; + if (jBlobBytes == NULL) { + __leave; + } BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes; if (bGeneratePrivateKeyBlob) { diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java index df2c3a87185..1635db730a5 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.util.*; import java.security.*; -import sun.security.action.GetPropertyAction; import sun.security.util.PropertyExpander; import sun.security.pkcs11.wrapper.*; @@ -58,15 +57,30 @@ final class Config { // will accept single threaded modules regardless of the setting in their // config files. private static final boolean staticAllowSingleThreadedModules; + private static final String osName; + private static final String osArch; static { - String p = "sun.security.pkcs11.allowSingleThreadedModules"; - String s = AccessController.doPrivileged(new GetPropertyAction(p)); - if ("false".equalsIgnoreCase(s)) { + List props = AccessController.doPrivileged( + new PrivilegedAction<>() { + @Override + public List run() { + return List.of( + System.getProperty( + "sun.security.pkcs11.allowSingleThreadedModules", + "true"), + System.getProperty("os.name"), + System.getProperty("os.arch")); + } + } + ); + if ("false".equalsIgnoreCase(props.get(0))) { staticAllowSingleThreadedModules = false; } else { staticAllowSingleThreadedModules = true; } + osName = props.get(1); + osArch = props.get(2); } private final static boolean DEBUG = false; @@ -650,8 +664,6 @@ final class Config { // replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC // and with "/amd64/" on Solaris AMD64. // On all other platforms, just turn it into a "/" - String osName = System.getProperty("os.name", ""); - String osArch = System.getProperty("os.arch", ""); String prefix = lib.substring(0, i); String suffix = lib.substring(i + 5); if (osName.equals("SunOS") && osArch.equals("sparcv9")) { diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java index 2dc66d2368b..c82e44b219f 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,8 @@ import javax.crypto.SecretKey; import sun.nio.ch.DirectBuffer; +import sun.security.util.MessageDigestSpi2; + import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; @@ -49,7 +51,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; * @author Andreas Sterbenz * @since 1.5 */ -final class P11Digest extends MessageDigestSpi implements Cloneable { +final class P11Digest extends MessageDigestSpi implements Cloneable, + MessageDigestSpi2 { /* fields initialized, no session acquired */ private final static int S_BLANK = 1; @@ -233,10 +236,11 @@ final class P11Digest extends MessageDigestSpi implements Cloneable { } // Called by SunJSSE via reflection during the SSL 3.0 handshake if - // the master secret is sensitive. We may want to consider making this - // method public in a future release. - protected void implUpdate(SecretKey key) throws InvalidKeyException { - + // the master secret is sensitive. + // Note: Change to protected after this method is moved from + // sun.security.util.MessageSpi2 interface to + // java.security.MessageDigestSpi class + public void engineUpdate(SecretKey key) throws InvalidKeyException { // SunJSSE calls this method only if the key does not have a RAW // encoding, i.e. if it is sensitive. Therefore, no point in calling // SecretKeyFactory to try to convert it. Just verify it ourselves. diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java index c12b820726f..f4edf8d1185 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java @@ -58,7 +58,7 @@ package sun.security.pkcs11.wrapper; */ public class Constants { - public static final String NEWLINE = System.getProperty("line.separator"); + public static final String NEWLINE = System.lineSeparator(); public static final String INDENT = " "; diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java index 090f96df227..a1a7cc15508 100644 --- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java +++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java @@ -50,12 +50,13 @@ public final class UcryptoProvider extends Provider { try { // cannot use LoadLibraryAction because that would make the native // library available to the bootclassloader, but we run in the - // extension classloader. - String osname = System.getProperty("os.name"); - if (osname.startsWith("SunOS")) { - provProp = AccessController.doPrivileged - (new PrivilegedAction>() { - public HashMap run() { + // platform classloader. + provProp = AccessController.doPrivileged + (new PrivilegedAction<>() { + @Override + public HashMap run() { + String osname = System.getProperty("os.name"); + if (osname.startsWith("SunOS")) { try { DEBUG = Boolean.parseBoolean(System.getProperty("com.oracle.security.ucrypto.debug")); String javaHome = System.getProperty("java.home"); @@ -66,14 +67,13 @@ public final class UcryptoProvider extends Provider { return new HashMap<>(); } catch (Error err) { if (DEBUG) err.printStackTrace(); - return null; } catch (SecurityException se) { if (DEBUG) se.printStackTrace(); - return null; } } - }); - } + return null; + } + }); if (provProp != null) { boolean[] result = loadLibraries(); if (result.length == 2) { diff --git a/jdk/src/jdk.httpserver/share/classes/module-info.java b/jdk/src/jdk.httpserver/share/classes/module-info.java index e26758b66e9..b01a3870d79 100644 --- a/jdk/src/jdk.httpserver/share/classes/module-info.java +++ b/jdk/src/jdk.httpserver/share/classes/module-info.java @@ -24,7 +24,6 @@ */ module jdk.httpserver { - requires java.logging; exports com.sun.net.httpserver; exports com.sun.net.httpserver.spi; diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java index eac2bc3ddf7..6c4780fcc4c 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -29,7 +29,8 @@ import java.io.*; import java.net.*; import javax.net.ssl.*; import java.util.*; -import java.util.logging.Logger; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.text.*; import com.sun.net.httpserver.*; @@ -221,7 +222,7 @@ class ExchangeImpl { Logger logger = server.getLogger(); String msg = "sendResponseHeaders: rCode = "+ rCode + ": forcing contentLen = -1"; - logger.warning (msg); + logger.log (Level.WARNING, msg); } contentLen = -1; } @@ -234,7 +235,7 @@ class ExchangeImpl { final Logger logger = server.getLogger(); String msg = "sendResponseHeaders: being invoked with a content length for a HEAD request"; - logger.warning (msg); + logger.log (Level.WARNING, msg); } noContentToSend = true; contentLen = 0; diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java index c9f31efb7d4..1107d5ef469 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java @@ -28,7 +28,8 @@ package sun.net.httpserver; import java.io.*; import javax.net.ssl.*; import java.nio.channels.*; -import java.util.logging.Logger; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; @@ -119,7 +120,7 @@ class HttpConnection { } closed = true; if (logger != null && chan != null) { - logger.finest ("Closing connection: " + chan.toString()); + logger.log (Level.TRACE, "Closing connection: " + chan.toString()); } if (!chan.isOpen()) { diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java index c7e7095be4b..bf58255773a 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java @@ -26,7 +26,7 @@ package sun.net.httpserver; import java.io.*; import java.util.*; -import java.util.logging.Logger; +import java.lang.System.Logger; import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java index a6b7427822d..0ff0e436828 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java @@ -25,7 +25,8 @@ package sun.net.httpserver; -import java.util.logging.Logger; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.security.PrivilegedAction; /** @@ -115,7 +116,8 @@ class ServerConfig { if (System.getProperty("sun.net.httpserver.readTimeout") !=null) { - logger.warning ("sun.net.httpserver.readTimeout "+ + logger.log (Level.WARNING, + "sun.net.httpserver.readTimeout "+ "property is no longer used. "+ "Use sun.net.httpserver.maxReqTime instead." ); @@ -123,7 +125,8 @@ class ServerConfig { if (System.getProperty("sun.net.httpserver.writeTimeout") !=null) { - logger.warning ("sun.net.httpserver.writeTimeout "+ + logger.log (Level.WARNING, + "sun.net.httpserver.writeTimeout "+ "property is no longer used. Use "+ "sun.net.httpserver.maxRspTime instead." ); @@ -131,7 +134,8 @@ class ServerConfig { if (System.getProperty("sun.net.httpserver.selCacheTimeout") !=null) { - logger.warning ("sun.net.httpserver.selCacheTimeout "+ + logger.log (Level.WARNING, + "sun.net.httpserver.selCacheTimeout "+ "property is no longer used." ); } diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index a8566e8f7b6..e384a849241 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -30,8 +30,8 @@ import java.io.*; import java.nio.channels.*; import java.util.*; import java.util.concurrent.*; -import java.util.logging.Logger; -import java.util.logging.Level; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import javax.net.ssl.*; import com.sun.net.httpserver.*; import java.security.AccessController; @@ -81,7 +81,7 @@ class ServerImpl implements TimeSource { final static boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1; private Timer timer, timer1; - private Logger logger; + private final Logger logger; private Thread dispatcherThread; ServerImpl ( @@ -90,7 +90,7 @@ class ServerImpl implements TimeSource { this.protocol = protocol; this.wrapper = wrapper; - this.logger = Logger.getLogger ("com.sun.net.httpserver"); + this.logger = System.getLogger ("com.sun.net.httpserver"); ServerConfig.checkLegacyProperties (logger); https = protocol.equalsIgnoreCase ("https"); this.address = addr; @@ -115,12 +115,12 @@ class ServerImpl implements TimeSource { if (timer1Enabled) { timer1 = new Timer ("server-timer1", true); timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS); - logger.config ("HttpServer timer1 enabled period in ms: "+TIMER_MILLIS); - logger.config ("MAX_REQ_TIME: "+MAX_REQ_TIME); - logger.config ("MAX_RSP_TIME: "+MAX_RSP_TIME); + logger.log (Level.DEBUG, "HttpServer timer1 enabled period in ms: ", TIMER_MILLIS); + logger.log (Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME); + logger.log (Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME); } events = new LinkedList(); - logger.config ("HttpServer created "+protocol+" "+ addr); + logger.log (Level.DEBUG, "HttpServer created "+protocol+" "+ addr); } public void bind (InetSocketAddress addr, int backlog) throws IOException { @@ -211,7 +211,7 @@ class ServerImpl implements TimeSource { dispatcherThread.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - logger.log(Level.FINER, "ServerImpl.stop: ", e); + logger.log (Level.TRACE, "ServerImpl.stop: ", e); } } } @@ -224,7 +224,7 @@ class ServerImpl implements TimeSource { } HttpContextImpl context = new HttpContextImpl (protocol, path, handler, this); contexts.add (context); - logger.config ("context created: " + path); + logger.log (Level.DEBUG, "context created: " + path); return context; } @@ -234,7 +234,7 @@ class ServerImpl implements TimeSource { } HttpContextImpl context = new HttpContextImpl (protocol, path, null, this); contexts.add (context); - logger.config ("context created: " + path); + logger.log (Level.DEBUG, "context created: " + path); return context; } @@ -243,7 +243,7 @@ class ServerImpl implements TimeSource { throw new NullPointerException ("null path parameter"); } contexts.remove (protocol, path); - logger.config ("context removed: " + path); + logger.log (Level.DEBUG, "context removed: " + path); } public synchronized void removeContext (HttpContext context) throws IllegalArgumentException { @@ -251,7 +251,7 @@ class ServerImpl implements TimeSource { throw new IllegalArgumentException ("wrong HttpContext type"); } contexts.remove ((HttpContextImpl)context); - logger.config ("context removed: " + context.getPath()); + logger.log (Level.DEBUG, "context removed: " + context.getPath()); } public InetSocketAddress getAddress() { @@ -310,7 +310,7 @@ class ServerImpl implements TimeSource { } } catch (IOException e) { logger.log ( - Level.FINER, "Dispatcher (1)", e + Level.TRACE, "Dispatcher (1)", e ); c.close(); } @@ -331,7 +331,7 @@ class ServerImpl implements TimeSource { idleConnections.add (c); } catch (IOException e) { dprint(e); - logger.log(Level.FINER, "Dispatcher(8)", e); + logger.log (Level.TRACE, "Dispatcher(8)", e); c.close(); } } @@ -416,9 +416,9 @@ class ServerImpl implements TimeSource { // call the selector just to process the cancelled keys selector.selectNow(); } catch (IOException e) { - logger.log (Level.FINER, "Dispatcher (4)", e); + logger.log (Level.TRACE, "Dispatcher (4)", e); } catch (Exception e) { - logger.log (Level.FINER, "Dispatcher (7)", e); + logger.log (Level.TRACE, "Dispatcher (7)", e); } } try {selector.close(); } catch (Exception e) {} @@ -427,7 +427,7 @@ class ServerImpl implements TimeSource { private void handleException (SelectionKey key, Exception e) { HttpConnection conn = (HttpConnection)key.attachment(); if (e != null) { - logger.log (Level.FINER, "Dispatcher (2)", e); + logger.log (Level.TRACE, "Dispatcher (2)", e); } closeConnection(conn); } @@ -439,10 +439,10 @@ class ServerImpl implements TimeSource { Exchange t = new Exchange (chan, protocol, conn); executor.execute (t); } catch (HttpError e1) { - logger.log (Level.FINER, "Dispatcher (4)", e1); + logger.log (Level.TRACE, "Dispatcher (4)", e1); closeConnection(conn); } catch (IOException e) { - logger.log (Level.FINER, "Dispatcher (5)", e); + logger.log (Level.TRACE, "Dispatcher (5)", e); closeConnection(conn); } } @@ -522,7 +522,8 @@ class ServerImpl implements TimeSource { newconnection = true; if (https) { if (sslContext == null) { - logger.warning ("SSL connection received. No https contxt created"); + logger.log (Level.WARNING, + "SSL connection received. No https contxt created"); throw new HttpError ("No SSL context established"); } sslStreams = new SSLStreams (ServerImpl.this, sslContext, chan); @@ -657,7 +658,7 @@ class ServerImpl implements TimeSource { } } catch (IOException e1) { - logger.log (Level.FINER, "ServerImpl.Exchange (1)", e1); + logger.log (Level.TRACE, "ServerImpl.Exchange (1)", e1); closeConnection(connection); } catch (NumberFormatException e3) { reject (Code.HTTP_BAD_REQUEST, @@ -666,7 +667,7 @@ class ServerImpl implements TimeSource { reject (Code.HTTP_BAD_REQUEST, requestLine, "URISyntaxException thrown"); } catch (Exception e4) { - logger.log (Level.FINER, "ServerImpl.Exchange (2)", e4); + logger.log (Level.TRACE, "ServerImpl.Exchange (2)", e4); closeConnection(connection); } } @@ -722,7 +723,7 @@ class ServerImpl implements TimeSource { closeConnection(connection); } } catch (IOException e) { - logger.log (Level.FINER, "ServerImpl.sendReply", e); + logger.log (Level.TRACE, "ServerImpl.sendReply", e); closeConnection(connection); } } @@ -730,7 +731,7 @@ class ServerImpl implements TimeSource { } void logReply (int code, String requestStr, String text) { - if (!logger.isLoggable(Level.FINE)) { + if (!logger.isLoggable(Level.DEBUG)) { return; } if (text == null) { @@ -744,7 +745,7 @@ class ServerImpl implements TimeSource { } String message = r + " [" + code + " " + Code.msg(code) + "] ("+text+")"; - logger.fine (message); + logger.log (Level.DEBUG, message); } long getTicks() { @@ -843,7 +844,7 @@ class ServerImpl implements TimeSource { } } for (HttpConnection c : toClose) { - logger.log (Level.FINE, "closing: no request: " + c); + logger.log (Level.DEBUG, "closing: no request: " + c); reqConnections.remove (c); allConnections.remove (c); c.close(); @@ -859,7 +860,7 @@ class ServerImpl implements TimeSource { } } for (HttpConnection c : toClose) { - logger.log (Level.FINE, "closing: no response: " + c); + logger.log (Level.DEBUG, "closing: no response: " + c); rspConnections.remove (c); allConnections.remove (c); c.close(); @@ -870,13 +871,13 @@ class ServerImpl implements TimeSource { } void logStackTrace (String s) { - logger.finest (s); + logger.log (Level.TRACE, s); StringBuilder b = new StringBuilder (); StackTraceElement[] e = Thread.currentThread().getStackTrace(); for (int i=0; i pushBackChar = new Stack(); - if (terminal.isAnsiSupported()) { + if (terminal.isAnsiSupported() && System.console() != null) { //detect the prompt length by reading the cursor position from the terminal //the real prompt length could differ from the simple prompt length due to //use of escape sequences: diff --git a/jdk/src/jdk.jartool/share/classes/module-info.java b/jdk/src/jdk.jartool/share/classes/module-info.java index cbf703263d4..536ca81b684 100644 --- a/jdk/src/jdk.jartool/share/classes/module-info.java +++ b/jdk/src/jdk.jartool/share/classes/module-info.java @@ -26,5 +26,7 @@ module jdk.jartool { exports com.sun.jarsigner; exports jdk.security.jarsigner; + + provides java.util.spi.ToolProvider with sun.tools.jar.JarToolProvider; } diff --git a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index 15b6c6d637e..846be10405c 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -50,6 +50,9 @@ import java.util.Map.Entry; import jdk.security.jarsigner.JarSigner; import jdk.security.jarsigner.JarSignerException; +import sun.security.pkcs.PKCS7; +import sun.security.pkcs.SignerInfo; +import sun.security.timestamp.TimestampToken; import sun.security.tools.KeyStoreUtil; import sun.security.x509.*; import sun.security.util.*; @@ -87,6 +90,15 @@ public class Main { private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds + private static final DisabledAlgorithmConstraints DISABLED_CHECK = + new DisabledAlgorithmConstraints( + DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); + + private static final Set DIGEST_PRIMITIVE_SET = Collections + .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); + private static final Set SIG_PRIMITIVE_SET = Collections + .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); + // Attention: // This is the entry that get launched by the security tool jarsigner. public static void main(String args[]) throws Exception { @@ -163,6 +175,8 @@ public class Main { private Throwable chainNotValidatedReason = null; + private boolean seeWeak = false; + CertificateFactory certificateFactory; CertPathValidator validator; PKIXParameters pkixParameters; @@ -628,6 +642,10 @@ public class Main { { boolean anySigned = false; // if there exists entry inside jar signed JarFile jf = null; + Map digestMap = new HashMap<>(); + Map sigMap = new HashMap<>(); + Map sigNameMap = new HashMap<>(); + Map unparsableSignatures = new HashMap<>(); try { jf = new JarFile(jarName, true); @@ -638,21 +656,50 @@ public class Main { while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); entriesVec.addElement(je); - InputStream is = null; - try { - is = jf.getInputStream(je); - while (is.read(buffer, 0, buffer.length) != -1) { - // we just read. this will throw a SecurityException - // if a signature/digest check fails. - } - } finally { - if (is != null) { - is.close(); + try (InputStream is = jf.getInputStream(je)) { + String name = je.getName(); + if (signatureRelated(name) + && SignatureFileVerifier.isBlockOrSF(name)) { + String alias = name.substring(name.lastIndexOf('/') + 1, + name.lastIndexOf('.')); + try { + if (name.endsWith(".SF")) { + Manifest sf = new Manifest(is); + boolean found = false; + for (Object obj : sf.getMainAttributes().keySet()) { + String key = obj.toString(); + if (key.endsWith("-Digest-Manifest")) { + digestMap.put(alias, + key.substring(0, key.length() - 16)); + found = true; + break; + } + } + if (!found) { + unparsableSignatures.putIfAbsent(alias, + String.format( + rb.getString("history.unparsable"), + name)); + } + } else { + sigNameMap.put(alias, name); + sigMap.put(alias, new PKCS7(is)); + } + } catch (IOException ioe) { + unparsableSignatures.putIfAbsent(alias, String.format( + rb.getString("history.unparsable"), name)); + } + } else { + while (is.read(buffer, 0, buffer.length) != -1) { + // we just read. this will throw a SecurityException + // if a signature/digest check fails. + } } } } Manifest man = jf.getManifest(); + boolean hasSignature = false; // The map to record display info, only used when -verbose provided // key: signer info string @@ -668,6 +715,10 @@ public class Main { while (e.hasMoreElements()) { JarEntry je = e.nextElement(); String name = je.getName(); + + hasSignature = hasSignature + || SignatureFileVerifier.isBlockOrSF(name); + CodeSigner[] signers = je.getCodeSigners(); boolean isSigned = (signers != null); anySigned |= isSigned; @@ -800,10 +851,11 @@ public class Main { System.out.println(rb.getString( ".X.not.signed.by.specified.alias.es.")); } - System.out.println(); } - if (man == null) + if (man == null) { + System.out.println(); System.out.println(rb.getString("no.manifest.")); + } // If signer is a trusted cert or private entry in user's own // keystore, it can be self-signed. @@ -811,9 +863,103 @@ public class Main { signerSelfSigned = false; } + // Even if the verbose option is not specified, all out strings + // must be generated so seeWeak can be updated. + if (!digestMap.isEmpty() + || !sigMap.isEmpty() + || !unparsableSignatures.isEmpty()) { + if (verbose != null) { + System.out.println(); + } + for (String s : sigMap.keySet()) { + if (!digestMap.containsKey(s)) { + unparsableSignatures.putIfAbsent(s, String.format( + rb.getString("history.nosf"), s)); + } + } + for (String s : digestMap.keySet()) { + PKCS7 p7 = sigMap.get(s); + if (p7 != null) { + String history; + try { + SignerInfo si = p7.getSignerInfos()[0]; + X509Certificate signer = si.getCertificate(p7); + String digestAlg = digestMap.get(s); + String sigAlg = AlgorithmId.makeSigAlg( + si.getDigestAlgorithmId().getName(), + si.getDigestEncryptionAlgorithmId().getName()); + PublicKey key = signer.getPublicKey(); + PKCS7 tsToken = si.getTsToken(); + if (tsToken != null) { + SignerInfo tsSi = tsToken.getSignerInfos()[0]; + X509Certificate tsSigner = tsSi.getCertificate(tsToken); + byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); + TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo); + PublicKey tsKey = tsSigner.getPublicKey(); + String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName(); + String tsSigAlg = AlgorithmId.makeSigAlg( + tsSi.getDigestAlgorithmId().getName(), + tsSi.getDigestEncryptionAlgorithmId().getName()); + Calendar c = Calendar.getInstance( + TimeZone.getTimeZone("UTC"), + Locale.getDefault(Locale.Category.FORMAT)); + c.setTime(tsTokenInfo.getDate()); + history = String.format( + rb.getString("history.with.ts"), + signer.getSubjectX500Principal(), + withWeak(digestAlg, DIGEST_PRIMITIVE_SET), + withWeak(sigAlg, SIG_PRIMITIVE_SET), + withWeak(key), + c, + tsSigner.getSubjectX500Principal(), + withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET), + withWeak(tsSigAlg, SIG_PRIMITIVE_SET), + withWeak(tsKey)); + } else { + history = String.format( + rb.getString("history.without.ts"), + signer.getSubjectX500Principal(), + withWeak(digestAlg, DIGEST_PRIMITIVE_SET), + withWeak(sigAlg, SIG_PRIMITIVE_SET), + withWeak(key)); + } + } catch (Exception e) { + // The only usage of sigNameMap, remember the name + // of the block file if it's invalid. + history = String.format( + rb.getString("history.unparsable"), + sigNameMap.get(s)); + } + if (verbose != null) { + System.out.println(history); + } + } else { + unparsableSignatures.putIfAbsent(s, String.format( + rb.getString("history.nobk"), s)); + } + } + if (verbose != null) { + for (String s : unparsableSignatures.keySet()) { + System.out.println(unparsableSignatures.get(s)); + } + } + } + System.out.println(); if (!anySigned) { - System.out.println(rb.getString( - "jar.is.unsigned.signatures.missing.or.not.parsable.")); + if (seeWeak) { + if (verbose != null) { + System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose")); + System.out.println("\n " + + DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS + + "=" + Security.getProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS)); + } else { + System.out.println(rb.getString("jar.treated.unsigned.see.weak")); + } + } else if (hasSignature) { + System.out.println(rb.getString("jar.treated.unsigned")); + } else { + System.out.println(rb.getString("jar.is.unsigned")); + } } else { boolean warningAppeared = false; boolean errorAppeared = false; @@ -837,7 +983,9 @@ public class Main { if (weakAlg != 0) { // In fact, jarsigner verification did not catch this // since it has not read the JarFile content itself. - // Everything is done with JarFile API. + // Everything is done with JarFile API. The signing + // history (digestMap etc) will show these info and + // print out proper warnings. } if (badKeyUsage) { @@ -928,6 +1076,26 @@ public class Main { System.exit(1); } + private String withWeak(String alg, Set primitiveSet) { + if (DISABLED_CHECK.permits(primitiveSet, alg, null)) { + return alg; + } else { + seeWeak = true; + return String.format(rb.getString("with.weak"), alg); + } + } + + private String withWeak(PublicKey key) { + if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { + return String.format( + rb.getString("key.bit"), KeyUtil.getKeySize(key)); + } else { + seeWeak = true; + return String.format( + rb.getString("key.bit.weak"), KeyUtil.getKeySize(key)); + } + } + private static MessageFormat validityTimeForm = null; private static MessageFormat notYetTimeForm = null; private static MessageFormat expiredTimeForm = null; @@ -1117,22 +1285,22 @@ public class Main { void signJar(String jarName, String alias) throws Exception { - DisabledAlgorithmConstraints dac = - new DisabledAlgorithmConstraints( - DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); - - if (digestalg != null && !dac.permits( - Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), digestalg, null)) { + if (digestalg != null && !DISABLED_CHECK.permits( + DIGEST_PRIMITIVE_SET, digestalg, null)) { weakAlg |= 1; } - if (tSADigestAlg != null && !dac.permits( - Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), tSADigestAlg, null)) { + if (tSADigestAlg != null && !DISABLED_CHECK.permits( + DIGEST_PRIMITIVE_SET, tSADigestAlg, null)) { weakAlg |= 4; } - if (sigalg != null && !dac.permits( - Collections.singleton(CryptoPrimitive.SIGNATURE), sigalg, null)) { + if (sigalg != null && !DISABLED_CHECK.permits( + SIG_PRIMITIVE_SET , sigalg, null)) { weakAlg |= 2; } + if (!DISABLED_CHECK.permits( + SIG_PRIMITIVE_SET, privateKey)) { + weakAlg |= 8; + } boolean aliasUsed = false; X509Certificate tsaCert = null; @@ -1377,6 +1545,11 @@ public class Main { rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), tSADigestAlg, "-tsadigestalg")); } + if ((weakAlg & 8) == 8) { + System.out.println(String.format( + rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."), + privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey))); + } } else { System.out.println(rb.getString("jar.signed.")); } diff --git a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java index 97ea20eb939..26e0553ebb2 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java @@ -142,12 +142,29 @@ public class Resources extends java.util.ListResourceBundle { {"no.manifest.", "no manifest."}, {".Signature.related.entries.","(Signature related entries)"}, {".Unsigned.entries.", "(Unsigned entries)"}, - {"jar.is.unsigned.signatures.missing.or.not.parsable.", - "jar is unsigned. (signatures missing or not parsable)"}, + {"jar.is.unsigned", + "jar is unsigned."}, + {"jar.treated.unsigned", + "WARNING: Signature is either not parsable or not verifiable, and the jar will be treated as unsigned. For more information, re-run jarsigner with debug enabled (-J-Djava.security.debug=jar)."}, + {"jar.treated.unsigned.see.weak", + "The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled.\n\nRe-run jarsigner with the -verbose option for more details."}, + {"jar.treated.unsigned.see.weak.verbose", + "WARNING: The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled by the security property:"}, {"jar.signed.", "jar signed."}, {"jar.signed.with.signer.errors.", "jar signed, with signer errors."}, {"jar.verified.", "jar verified."}, {"jar.verified.with.signer.errors.", "jar verified, with signer errors."}, + + {"history.with.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s\n Timestamped by \"%6$s\" on %5$tc\n Timestamp digest algorithm: %7$s\n Timestamp signature algorithm: %8$s, %9$s"}, + {"history.without.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s"}, + {"history.unparsable", "- Unparsable signature-related file %s"}, + {"history.nosf", "- Missing signature-related file META-INF/%s.SF"}, + {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"}, + + {"with.weak", "%s (weak)"}, + {"key.bit", "%d-bit key"}, + {"key.bit.weak", "%d-bit key (weak)"}, + {"jarsigner.", "jarsigner: "}, {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", "signature filename must consist of the following characters: A-Z, 0-9, _ or -"}, @@ -246,6 +263,8 @@ public class Resources extends java.util.ListResourceBundle { "The signer's certificate is self-signed."}, {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.", "The %1$s algorithm specified for the %2$s option is considered a security risk."}, + {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.", + "The %s signing key has a keysize of %d which is considered a security risk."}, {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.reason.1", "This jar contains entries whose certificate chain is not validated. Reason: %s"}, {"no.timestamp.signing", diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java index 165a424d9ca..17b4c1725cc 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java @@ -27,6 +27,7 @@ package sun.tools.jar; import java.io.File; import java.io.PrintStream; +import java.io.PrintWriter; import java.lang.module.ModuleFinder; import java.lang.module.ModuleDescriptor.Version; import java.nio.file.Path; @@ -253,7 +254,8 @@ class GNUStyleOptions { // process options for (; count < args.length; count++) { - if (args[count].charAt(0) != '-' || args[count].equals("-C")) + if (args[count].charAt(0) != '-' || args[count].equals("-C") + || args[count].equals("--release")) break; String name = args[count]; @@ -289,7 +291,7 @@ class GNUStyleOptions { throw new BadArgs("error.unrecognized.option", name).showUsage(true); } - static void printHelp(PrintStream out) { + static void printHelp(PrintWriter out) { out.format("%s%n", Main.getMsg("main.help.preopt")); for (OptionType type : OptionType.values()) { boolean typeHeadingWritten = false; @@ -312,16 +314,16 @@ class GNUStyleOptions { out.format("%n%s%n%n", Main.getMsg("main.help.postopt")); } - static void printCompatHelp(PrintStream out) { + static void printCompatHelp(PrintWriter out) { out.format("%s%n", Main.getMsg("usage.compat")); } - static void printUsageSummary(PrintStream out) { + static void printUsageSummary(PrintWriter out) { out.format("%s%n", Main.getMsg("main.usage.summary")); out.format("%s%n", Main.getMsg("main.usage.summary.try")); } - static void printVersion(PrintStream out) { + static void printVersion(PrintWriter out) { out.format("%s %s%n", "jar", System.getProperty("java.version")); } } diff --git a/nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java similarity index 72% rename from nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java rename to jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java index 0a6283599ec..959db36a2f1 100644 --- a/nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * 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,11 +23,18 @@ * questions. */ -package jdk.dynalink.test; +package sun.tools.jar; -/** - * Exception used to signal to the test method that the control has reached auto loaded - * dynamic linker. - */ -public final class ReachedAutoLoadedDynamicLinkerException extends RuntimeException { +import java.io.PrintWriter; +import java.util.spi.ToolProvider; + +public class JarToolProvider implements ToolProvider { + public String name() { + return "jar"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + boolean ok = new Main(out, err, name()).run(args); + return ok ? 0 : 1; + } } diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index 41ccfe9f774..6aa65550140 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -76,7 +76,7 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; public class Main { String program; - PrintStream out, err; + PrintWriter out, err; String fname, mname, ename; String zname = ""; String rootjar = null; @@ -189,9 +189,9 @@ class Main { USAGE_SUMMARY(GNUStyleOptions::printUsageSummary), VERSION(GNUStyleOptions::printVersion); - private Consumer printFunction; - Info(Consumer f) { this.printFunction = f; } - void print(PrintStream out) { printFunction.accept(out); } + private Consumer printFunction; + Info(Consumer f) { this.printFunction = f; } + void print(PrintWriter out) { printFunction.accept(out); } }; Info info; @@ -252,6 +252,12 @@ class Main { } public Main(PrintStream out, PrintStream err, String program) { + this.out = new PrintWriter(out, true); + this.err = new PrintWriter(err, true); + this.program = program; + } + + public Main(PrintWriter out, PrintWriter err, String program) { this.out = out; this.err = err; this.program = program; diff --git a/jdk/src/jdk.jdwp.agent/share/native/include/jdwpTransport.h b/jdk/src/jdk.jdwp.agent/share/native/include/jdwpTransport.h index c3342d9510a..32ccdeae87f 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/include/jdwpTransport.h +++ b/jdk/src/jdk.jdwp.agent/share/native/include/jdwpTransport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,6 +96,11 @@ typedef struct { */ enum { + /* + * If additional flags are added that apply to jdwpCmdPacket, + * then debugLoop.c: reader() will need to be updated to + * accept more than JDWPTRANSPORT_FLAGS_NONE. + */ JDWPTRANSPORT_FLAGS_NONE = 0x0, JDWPTRANSPORT_FLAGS_REPLY = 0x80 }; diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c index f49b53c7a69..18389e2715c 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -218,6 +218,20 @@ reader(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) if (rc != 0 || (rc == 0 && packet.type.cmd.len == 0)) { shouldListen = JNI_FALSE; notifyTransportError(); + } else if (packet.type.cmd.flags != JDWPTRANSPORT_FLAGS_NONE) { + /* + * Close the connection when we get a jdwpCmdPacket with an + * invalid flags field value. This is a protocol violation + * so we drop the connection. Also this could be a web + * browser generating an HTTP request that passes the JDWP + * handshake. HTTP requests requires that everything be in + * the ASCII printable range so a flags value of + * JDWPTRANSPORT_FLAGS_NONE(0) cannot be generated via HTTP. + */ + ERROR_MESSAGE(("Received jdwpPacket with flags != 0x%d (actual=0x%x) when a jdwpCmdPacket was expected.", + JDWPTRANSPORT_FLAGS_NONE, packet.type.cmd.flags)); + shouldListen = JNI_FALSE; + notifyTransportError(); } else { cmd = &packet.type.cmd; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java index 405ba61a57b..4384eb05d90 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java @@ -37,17 +37,17 @@ import java.io.InputStream; import java.io.UncheckedIOException; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.io.UncheckedIOException; import java.io.Writer; import java.lang.module.ModuleDescriptor; import java.nio.charset.StandardCharsets; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; -import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -55,7 +55,8 @@ import java.util.Objects; import java.util.Optional; import java.util.Properties; import java.util.Set; -import java.util.stream.Collectors; +import static java.util.stream.Collectors.*; + import jdk.tools.jlink.internal.BasicImageWriter; import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile; import jdk.tools.jlink.internal.ExecutableImage; @@ -171,15 +172,36 @@ public final class DefaultImageBuilder implements ImageBuilder { Properties release = releaseProperties(files); Path bin = root.resolve("bin"); - files.entries().forEach(f -> { - if (!f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { + // check any duplicated resource files + Map> duplicates = new HashMap<>(); + files.entries() + .filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE) + .collect(groupingBy(this::entryToImagePath, + mapping(ResourcePoolEntry::moduleName, toSet()))) + .entrySet() + .stream() + .filter(e -> e.getValue().size() > 1) + .forEach(e -> duplicates.put(e.getKey(), e.getValue())); + + // write non-classes resource files to the image + files.entries() + .filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE) + .forEach(f -> { try { accept(f); + } catch (FileAlreadyExistsException e) { + // error for duplicated entries + Path path = entryToImagePath(f); + UncheckedIOException x = + new UncheckedIOException(path + " duplicated in " + + duplicates.get(path), e); + x.addSuppressed(e); + throw x; } catch (IOException ioExp) { throw new UncheckedIOException(ioExp); } - } - }); + }); + files.moduleView().modules().forEach(m -> { // Only add modules that contain packages if (!m.packages().isEmpty()) { @@ -226,7 +248,7 @@ public final class DefaultImageBuilder implements ImageBuilder { version(). stream(). map(Object::toString). - collect(Collectors.joining(".")); + collect(joining(".")); } private static String quote(String str) { @@ -344,28 +366,69 @@ public final class DefaultImageBuilder implements ImageBuilder { } } - private void accept(ResourcePoolEntry file) throws IOException { - String fullPath = file.path(); - String module = "/" + file.moduleName() + "/"; - String filename = fullPath.substring(module.length()); + /** + * Returns the file name of this entry + */ + private String entryToFileName(ResourcePoolEntry entry) { + if (entry.type() == ResourcePoolEntry.Type.CLASS_OR_RESOURCE) + throw new IllegalArgumentException("invalid type: " + entry); + + String module = "/" + entry.moduleName() + "/"; + String filename = entry.path().substring(module.length()); // Remove radical native|config|... - filename = filename.substring(filename.indexOf('/') + 1); + return filename.substring(filename.indexOf('/') + 1); + } + + /** + * Returns the path of the given entry to be written in the image + */ + private Path entryToImagePath(ResourcePoolEntry entry) { + switch (entry.type()) { + case NATIVE_LIB: + String filename = entryToFileName(entry); + return Paths.get(nativeDir(filename), filename); + case NATIVE_CMD: + return Paths.get("bin", entryToFileName(entry)); + case CONFIG: + return Paths.get("conf", entryToFileName(entry)); + case HEADER_FILE: + return Paths.get("include", entryToFileName(entry)); + case MAN_PAGE: + return Paths.get("man", entryToFileName(entry)); + case TOP: + return Paths.get(entryToFileName(entry)); + case OTHER: + return Paths.get("other", entryToFileName(entry)); + default: + throw new IllegalArgumentException("invalid type: " + entry); + } + } + + private void accept(ResourcePoolEntry file) throws IOException { try (InputStream in = file.content()) { switch (file.type()) { case NATIVE_LIB: - writeEntry(in, destFile(nativeDir(filename), filename)); + Path dest = root.resolve(entryToImagePath(file)); + writeEntry(in, dest); break; case NATIVE_CMD: - Path path = destFile("bin", filename); - writeEntry(in, path); - path.toFile().setExecutable(true); + Path p = root.resolve(entryToImagePath(file)); + writeEntry(in, p); + p.toFile().setExecutable(true); break; case CONFIG: - writeEntry(in, destFile("conf", filename)); + writeEntry(in, root.resolve(entryToImagePath(file))); + break; + case HEADER_FILE: + writeEntry(in, root.resolve(entryToImagePath(file))); + break; + case MAN_PAGE: + writeEntry(in, root.resolve(entryToImagePath(file))); break; case TOP: break; case OTHER: + String filename = entryToFileName(file); if (file instanceof SymImageFile) { SymImageFile sym = (SymImageFile) file; Path target = root.resolve(sym.getTargetPath()); @@ -379,15 +442,11 @@ public final class DefaultImageBuilder implements ImageBuilder { } break; default: - throw new InternalError("unexpected entry: " + fullPath); + throw new InternalError("unexpected entry: " + file.path()); } } } - private Path destFile(String dir, String filename) { - return root.resolve(dir).resolve(filename); - } - private void writeEntry(InputStream in, Path dstFile) throws IOException { Objects.requireNonNull(in); Objects.requireNonNull(dstFile); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java index e2c4c49ad66..9c896071e57 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java @@ -44,9 +44,11 @@ public interface Archive { public static enum EntryType { MODULE_NAME, CLASS_OR_RESOURCE, + CONFIG, NATIVE_LIB, NATIVE_CMD, - CONFIG, + HEADER_FILE, + MAN_PAGE, SERVICE; } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java index c81cc54050a..01fd19d062a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java @@ -73,6 +73,10 @@ final class ArchiveEntryResourcePoolEntry extends AbstractResourcePoolEntry { return ResourcePoolEntry.Type.NATIVE_CMD; case NATIVE_LIB: return ResourcePoolEntry.Type.NATIVE_LIB; + case HEADER_FILE: + return ResourcePoolEntry.Type.HEADER_FILE; + case MAN_PAGE: + return ResourcePoolEntry.Type.MAN_PAGE; default: return ResourcePoolEntry.Type.OTHER; } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java index d342550029b..794010634e1 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import jdk.tools.jlink.builder.ImageBuilder; -import jdk.tools.jlink.Jlink; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.PluginException; import jdk.tools.jlink.plugin.Plugin.Category; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java similarity index 98% rename from jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java rename to jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java index 1a23e19fa2b..615b7a8349c 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.tools.jlink; +package jdk.tools.jlink.internal; import java.lang.reflect.Layer; import java.nio.ByteOrder; @@ -32,12 +32,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import jdk.tools.jlink.internal.ExecutableImage; -import jdk.tools.jlink.internal.JlinkTask; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.PluginException; import jdk.tools.jlink.builder.ImageBuilder; -import jdk.tools.jlink.internal.PluginRepository; /** * API to call jlink. diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkPermission.java similarity index 97% rename from jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java rename to jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkPermission.java index 0270f58de55..f1725e77ee2 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkPermission.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.tools.jlink; +package jdk.tools.jlink.internal; import java.security.BasicPermission; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index dfecf9e0c3a..90ca7fb397a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -46,11 +46,11 @@ import jdk.internal.module.ConfigurableModuleFinder; import jdk.internal.module.ConfigurableModuleFinder.Phase; import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JLINK_BUNDLE; +import jdk.tools.jlink.internal.Jlink.JlinkConfiguration; +import jdk.tools.jlink.internal.Jlink.PluginsConfiguration; import jdk.tools.jlink.internal.TaskHelper.Option; import jdk.tools.jlink.internal.TaskHelper.OptionsHelper; import jdk.tools.jlink.internal.ImagePluginStack.ImageProvider; -import jdk.tools.jlink.Jlink.JlinkConfiguration; -import jdk.tools.jlink.Jlink.PluginsConfiguration; import jdk.tools.jlink.plugin.PluginException; import jdk.tools.jlink.builder.DefaultImageBuilder; import jdk.tools.jlink.plugin.Plugin; @@ -153,7 +153,7 @@ public class JlinkTask { = taskHelper.newOptionsHelper(JlinkTask.class, recognizedOptions); private PrintWriter log; - void setLog(PrintWriter out) { + void setLog(PrintWriter out, PrintWriter err) { log = out; taskHelper.setLog(log); } @@ -182,7 +182,8 @@ public class JlinkTask { int run(String[] args) { if (log == null) { - setLog(new PrintWriter(System.out, true)); + setLog(new PrintWriter(System.out, true), + new PrintWriter(System.err, true)); } try { optionsHelper.handleOptions(this, args); @@ -212,8 +213,8 @@ public class JlinkTask { } return EXIT_OK; - } catch (UncheckedIOException | PluginException | IllegalArgumentException | - IOException | ResolutionException e) { + } catch (PluginException | IllegalArgumentException | + UncheckedIOException |IOException | ResolutionException e) { log.println(taskHelper.getMessage("error.prefix") + " " + e.getMessage()); if (DEBUG) { e.printStackTrace(log); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java index c70cb104d5b..0a528ee9a7b 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java @@ -128,12 +128,16 @@ public class JmodArchive implements Archive { switch (section) { case CLASSES: return EntryType.CLASS_OR_RESOURCE; + case CONFIG: + return EntryType.CONFIG; case NATIVE_LIBS: return EntryType.NATIVE_LIB; case NATIVE_CMDS: return EntryType.NATIVE_CMD; - case CONFIG: - return EntryType.CONFIG; + case HEADER_FILES: + return EntryType.HEADER_FILE; + case MAN_PAGES: + return EntryType.MAN_PAGE; default: throw new InternalError("unexpected entry: " + section); } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java index 651480de253..26914aca208 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java @@ -26,25 +26,41 @@ package jdk.tools.jlink.internal; import java.io.*; +import java.util.spi.ToolProvider; public class Main { public static void main(String... args) throws Exception { - JlinkTask t = new JlinkTask(); - int rc = t.run(args); - System.exit(rc); + System.exit(run(new PrintWriter(System.out, true), + new PrintWriter(System.err, true), + args)); } - /** * Entry point that does not call System.exit. * - * @param args command line arguments * @param out output stream + * @param err error output stream + * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - public static int run(String[] args, PrintWriter out) { + public static int run(PrintWriter out, PrintWriter err, String... args) { + if (System.getSecurityManager() != null) { + System.getSecurityManager(). + checkPermission(new JlinkPermission("jlink")); + } + JlinkTask t = new JlinkTask(); - t.setLog(out); + t.setLog(out, err); return t.run(args); } + + public static class JlinkToolProvider implements ToolProvider { + public String name() { + return "jlink"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(out, err, args); + } + } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java index 4524f199725..d8bad6bf4af 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java @@ -49,13 +49,14 @@ import java.util.Set; import jdk.internal.module.ConfigurableModuleFinder; import jdk.internal.module.ConfigurableModuleFinder.Phase; -import jdk.tools.jlink.Jlink; -import jdk.tools.jlink.Jlink.PluginsConfiguration; +import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin; +import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.Plugin.Category; import jdk.tools.jlink.builder.DefaultImageBuilder; import jdk.tools.jlink.builder.ImageBuilder; import jdk.tools.jlink.plugin.PluginException; +import jdk.tools.jlink.internal.Jlink.PluginsConfiguration; import jdk.tools.jlink.internal.plugins.PluginsResourceBundle; import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin; import jdk.tools.jlink.internal.plugins.StripDebugPlugin; @@ -323,6 +324,20 @@ public final class TaskHelper { addArgumentMap(plugin); }, "-G"); mainOptions.add(plugOption); + } else if (plugin instanceof ExcludeJmodSectionPlugin) { + plugOption = new PlugOption(false, (task, opt, arg) -> { + Map m = addArgumentMap(plugin); + m.put(ExcludeJmodSectionPlugin.NAME, + ExcludeJmodSectionPlugin.MAN_PAGES); + }, "--no-man-pages"); + mainOptions.add(plugOption); + + plugOption = new PlugOption(false, (task, opt, arg) -> { + Map m = addArgumentMap(plugin); + m.put(ExcludeJmodSectionPlugin.NAME, + ExcludeJmodSectionPlugin.INCLUDE_HEADER_FILES); + }, "--no-header-files"); + mainOptions.add(plugOption); } } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java index 6b05145f278..0d2adf63221 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java @@ -26,8 +26,8 @@ package jdk.tools.jlink.internal.packager; -import jdk.tools.jlink.Jlink; import jdk.tools.jlink.builder.DefaultImageBuilder; +import jdk.tools.jlink.internal.Jlink; import jdk.tools.jlink.internal.JlinkTask; import jdk.tools.jlink.plugin.Plugin; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java new file mode 100644 index 00000000000..ef497febcd3 --- /dev/null +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.tools.jlink.internal.plugins; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import jdk.tools.jlink.plugin.Plugin; +import jdk.tools.jlink.plugin.PluginException; +import jdk.tools.jlink.plugin.ResourcePool; +import jdk.tools.jlink.plugin.ResourcePoolBuilder; +import jdk.tools.jlink.plugin.ResourcePoolEntry.Type; + +/** + * + * A plugin to exclude a JMOD section such as man pages or header files + */ +public final class ExcludeJmodSectionPlugin implements Plugin { + + public static final String NAME = "exclude-jmod-section"; + public static final String MAN_PAGES = "man"; + public static final String INCLUDE_HEADER_FILES = "headers"; + + private final Set filters = new HashSet<>(); + + @Override + public String getName() { + return NAME; + } + + @Override + public void configure(Map config) { + String arg = config.get(NAME); + if (arg.isEmpty()) { + throw new PluginException("Section name must be specified"); + } + + switch (arg) { + case MAN_PAGES: + filters.add(Type.MAN_PAGE); + break; + case INCLUDE_HEADER_FILES: + filters.add(Type.HEADER_FILE); + break; + default: + throw new PluginException("Invalid section name: " + arg); + } + } + + @Override + public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { + in.transformAndCopy(entry -> { + // filter entries whose type corresponds to the specified JMOD section + if (filters.contains(entry.type())) { + entry = null; + } + return entry; + }, out); + return out.build(); + } + + @Override + public Category getType() { + return Category.FILTER; + } + + @Override + public String getDescription() { + return PluginsResourceBundle.getDescription(NAME); + } + + @Override + public boolean hasArguments() { + return true; + } + + @Override + public String getArgumentsDescription() { + return PluginsResourceBundle.getArgument(NAME); + } +} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java index 927d4c6c89e..9dcc83abf8a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java @@ -24,13 +24,12 @@ */ package jdk.tools.jlink.plugin; -import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UncheckedIOException; -import java.nio.file.Files; import java.nio.file.Path; + import jdk.tools.jlink.internal.ResourcePoolEntryFactory; /** @@ -64,6 +63,8 @@ public interface ResourcePoolEntry { CONFIG, NATIVE_CMD, NATIVE_LIB, + HEADER_FILE, + MAN_PAGE, TOP, OTHER } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 1303d5745c5..b990e2a6069 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -68,6 +68,12 @@ exclude-resources.argument= resources to exclude exclude-resources.description=\ Specify resources to exclude. e.g.: **.jcov,glob:**/META-INF/** +exclude-jmod-section.argument=\n\ +where is \"man\" or \"headers". + +exclude-jmod-section.description=\ +Specify a JMOD section to exclude + generate-jli-classes.argument= generate-jli-classes.description=\ @@ -145,6 +151,12 @@ plugin.opt.c=\ plugin.opt.G=\ \ -G, --strip-debug Strip debug information +plugin.opt.no-man-pages=\ +\ --no-man-pages Exclude man pages + +plugin.opt.no-header-files=\ +\ --no-header-files Exclude include header files + main.plugin.name=\ \Plugin Name diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index 6c23ce01bba..d5db2a00991 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.io.PrintWriter; import java.io.UncheckedIOException; import java.lang.module.Configuration; import java.lang.module.ModuleReader; @@ -136,8 +137,8 @@ public class JmodTask { private static final String MODULE_INFO = "module-info.class"; private Options options; - private PrintStream out = System.out; - void setLog(PrintStream out) { + private PrintWriter out = new PrintWriter(System.out, true); + void setLog(PrintWriter out, PrintWriter err) { this.out = out; } @@ -164,6 +165,8 @@ public class JmodTask { List cmds; List configs; List libs; + List headerFiles; + List manPages; ModuleFinder moduleFinder; Version moduleVersion; String mainClass; @@ -345,6 +348,9 @@ public class JmodTask { final List libs = options.libs; final List configs = options.configs; final List classpath = options.classpath; + final List headerFiles = options.headerFiles; + final List manPages = options.manPages; + final Version moduleVersion = options.moduleVersion; final String mainClass = options.mainClass; final String osName = options.osName; @@ -368,6 +374,9 @@ public class JmodTask { processSection(out, Section.NATIVE_CMDS, cmds); processSection(out, Section.NATIVE_LIBS, libs); processSection(out, Section.CONFIG, configs); + processSection(out, Section.HEADER_FILES, headerFiles); + processSection(out, Section.MAN_PAGES, manPages); + } /** @@ -595,7 +604,7 @@ public class JmodTask { return ""; } - void processClasses(JmodOutputStream zos, List classpaths) + void processClasses(JmodOutputStream out, List classpaths) throws IOException { if (classpaths == null) @@ -603,24 +612,24 @@ public class JmodTask { for (Path p : classpaths) { if (Files.isDirectory(p)) { - processSection(zos, Section.CLASSES, p); + processSection(out, Section.CLASSES, p); } else if (Files.isRegularFile(p) && p.toString().endsWith(".jar")) { try (JarFile jf = new JarFile(p.toFile())) { - JarEntryConsumer jec = new JarEntryConsumer(zos, jf); + JarEntryConsumer jec = new JarEntryConsumer(out, jf); jf.stream().filter(jec).forEach(jec); } } } } - void processSection(JmodOutputStream zos, Section section, List paths) + void processSection(JmodOutputStream out, Section section, List paths) throws IOException { if (paths == null) return; for (Path p : paths) - processSection(zos, section, p); + processSection(out, section, p); } void processSection(JmodOutputStream out, Section section, Path top) @@ -1194,6 +1203,12 @@ public class JmodTask { = parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help")) .forHelp(); + OptionSpec headerFiles + = parser.accepts("header-files", getMessage("main.opt.header-files")) + .withRequiredArg() + .withValuesSeparatedBy(File.pathSeparatorChar) + .withValuesConvertedBy(DirPathConverter.INSTANCE); + OptionSpec libs = parser.accepts("libs", getMessage("main.opt.libs")) .withRequiredArg() @@ -1205,6 +1220,12 @@ public class JmodTask { .withRequiredArg() .describedAs(getMessage("main.opt.main-class.arg")); + OptionSpec manPages + = parser.accepts("man-pages", getMessage("main.opt.man-pages")) + .withRequiredArg() + .withValuesSeparatedBy(File.pathSeparatorChar) + .withValuesConvertedBy(DirPathConverter.INSTANCE); + OptionSpec modulePath = parser.acceptsAll(Set.of("p", "module-path"), getMessage("main.opt.module-path")) @@ -1271,6 +1292,10 @@ public class JmodTask { options.excludes = opts.valuesOf(excludes); if (opts.has(libs)) options.libs = opts.valuesOf(libs); + if (opts.has(headerFiles)) + options.headerFiles = opts.valuesOf(headerFiles); + if (opts.has(manPages)) + options.manPages = opts.valuesOf(manPages); if (opts.has(modulePath)) { Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]); options.moduleFinder = ModuleFinder.of(dirs); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java index 227f9948e65..1d069607d05 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java @@ -26,6 +26,7 @@ package jdk.tools.jmod; import java.io.*; +import java.util.spi.ToolProvider; public class Main { public static void main(String... args) throws Exception { @@ -37,13 +38,24 @@ public class Main { /** * Entry point that does not call System.exit. * - * @param args command line arguments * @param out output stream + * @param err error output stream + * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - public static int run(String[] args, PrintStream out) { + public static int run(PrintWriter out, PrintWriter err, String... args) { JmodTask t = new JmodTask(); - t.setLog(out); + t.setLog(out, err); return t.run(args); } + + public static class JmodToolProvider implements ToolProvider { + public String name() { + return "jmod"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(out, err, args); + } + } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties index d6531f70ca4..3156a53f983 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties @@ -54,9 +54,11 @@ main.opt.dry-run=Dry run of hash mode main.opt.exclude=Exclude files matching the supplied comma separated pattern\ \ list, each element using one the following forms: ,\ \ glob: or regex: +main.opt.header-files=Location of header files main.opt.module-version= Module version main.opt.main-class=Main class main.opt.main-class.arg=class-name +main.opt.man-pages=Location of man pages main.opt.os-name=Operating system name main.opt.os-name.arg=os-name main.opt.os-arch=Operating system architecture diff --git a/jdk/src/jdk.jlink/share/classes/module-info.java b/jdk/src/jdk.jlink/share/classes/module-info.java index 0b1995129f2..37fced0d189 100644 --- a/jdk/src/jdk.jlink/share/classes/module-info.java +++ b/jdk/src/jdk.jlink/share/classes/module-info.java @@ -31,10 +31,14 @@ module jdk.jlink { uses jdk.tools.jlink.plugin.Plugin; + provides java.util.spi.ToolProvider with jdk.tools.jmod.Main.JmodToolProvider; + provides java.util.spi.ToolProvider with jdk.tools.jlink.internal.Main.JlinkToolProvider; + provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludePlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin; + provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin; diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp index 60aa3bfdf0c..435d5ddcf0f 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp +++ b/jdk/src/jdk.pack200/share/native/common-unpack/unpack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,7 +174,10 @@ struct entry { const char* utf8String() { assert(tagMatches(CONSTANT_Utf8)); - assert(value.b.len == strlen((const char*)value.b.ptr)); + if (value.b.len != strlen((const char*)value.b.ptr)) { + unpack_abort("bad utf8 encoding"); + // and fall through + } return (const char*)value.b.ptr; } @@ -1319,10 +1322,10 @@ void unpacker::read_signature_values(entry* cpMap, int len) { CHECK; int nc = 0; - for ( const char* ncp = form.utf8String() ; *ncp; ncp++) { - if (*ncp == 'L') nc++; + for (int j = 0; j < (int)form.value.b.len; j++) { + int c = form.value.b.ptr[j]; + if (c == 'L') nc++; } - ncTotal += nc; e.refs = U_NEW(entry*, cpMap[i].nrefs = 1 + nc); CHECK; @@ -2830,6 +2833,7 @@ void unpacker::putlayout(band** body) { } assert(!b.le_bci || prevBCI == (int)to_bci(prevBII)); + CHECK; switch (b.le_len) { case 0: break; case 1: putu1(x); break; @@ -4026,6 +4030,10 @@ uint unpacker::to_bci(uint bii) { uint len = bcimap.length(); uint* map = (uint*) bcimap.base(); assert(len > 0); // must be initialized before using to_bci + if (len == 0) { + abort("bad bcimap"); + return 0; + } if (bii < len) return map[bii]; // Else it's a fractional or out-of-range BCI. @@ -4048,6 +4056,7 @@ void unpacker::put_stackmap_type() { break; case 8: // (8) [PH] putu2(to_bci(code_StackMapTable_P.getInt())); + CHECK; break; } } @@ -4095,6 +4104,7 @@ void unpacker::write_bc_ops() { CHECK; for (int curIP = 0; ; curIP++) { + CHECK; int curPC = (int)(wpoffset() - codeBase); bcimap.add(curPC); ensure_put_space(10); // covers most instrs w/o further bounds check @@ -4336,6 +4346,7 @@ void unpacker::write_bc_ops() { int curIP = code_fixup_source.get(i); int destIP = curIP + bc_label.getInt(); int span = to_bci(destIP) - to_bci(curIP); + CHECK; switch (type) { case 2: putu2_at(bp, (ushort)span); break; case 4: putu4_at(bp, span); break; @@ -4532,11 +4543,13 @@ int unpacker::write_attrs(int attrc, julong indexBits) { if (tag <= 127) { // (64-127) [(2)] if (tag >= 64) put_stackmap_type(); + CHECK_0; } else if (tag <= 251) { // (247) [(1)(2)] // (248-251) [(1)] if (tag >= 247) putu2(code_StackMapTable_offset.getInt()); if (tag == 247) put_stackmap_type(); + CHECK_0; } else if (tag <= 254) { // (252) [(1)(2)] // (253) [(1)(2)(2)] @@ -4563,6 +4576,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { putu2(count = code_LineNumberTable_N.getInt()); for (j = 0; j < count; j++) { putu2(to_bci(code_LineNumberTable_bci_P.getInt())); + CHECK_0; putu2(code_LineNumberTable_line.getInt()); } break; @@ -4573,9 +4587,11 @@ int unpacker::write_attrs(int attrc, julong indexBits) { for (j = 0; j < count; j++) { int bii = code_LocalVariableTable_bci_P.getInt(); int bci = to_bci(bii); + CHECK_0; putu2(bci); bii += code_LocalVariableTable_span_O.getInt(); putu2(to_bci(bii) - bci); + CHECK_0; putref(code_LocalVariableTable_name_RU.getRefN()); CHECK_0; putref(code_LocalVariableTable_type_RS.getRefN()); @@ -4590,9 +4606,11 @@ int unpacker::write_attrs(int attrc, julong indexBits) { for (j = 0; j < count; j++) { int bii = code_LocalVariableTypeTable_bci_P.getInt(); int bci = to_bci(bii); + CHECK_0; putu2(bci); bii += code_LocalVariableTypeTable_span_O.getInt(); putu2(to_bci(bii) - bci); + CHECK_0; putref(code_LocalVariableTypeTable_name_RU.getRefN()); CHECK_0; putref(code_LocalVariableTypeTable_type_RS.getRefN()); @@ -5036,6 +5054,7 @@ unpacker::file* unpacker::get_next_file() { entry* e = file_name.getRef(); CHECK_0; cur_file.name = e->utf8String(); + CHECK_0; bool haveLongSize = (testBit(archive_options, AO_HAVE_FILE_SIZE_HI)); cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize); if (testBit(archive_options, AO_HAVE_FILE_MODTIME)) diff --git a/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java index 85f4e4cb299..7e3fa5c337b 100644 --- a/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java +++ b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java @@ -25,24 +25,34 @@ package sun.reflect; +import java.io.OptionalDataException; +import java.lang.invoke.MethodHandle; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; +/** + * ReflectionFactory supports custom serialization. + * Its methods support the creation of uninitialized objects, invoking serialization + * private methods for readObject, writeObject, readResolve, and writeReplace. + *

+ * ReflectionFactory access is restricted, if a security manager is active, + * unless the permission {@code RuntimePermission("reflectionFactoryAccess")} + * is granted. + */ public class ReflectionFactory { private static final ReflectionFactory soleInstance = new ReflectionFactory(); - private final jdk.internal.reflect.ReflectionFactory delegate; - - private ReflectionFactory() { - delegate = AccessController.doPrivileged( + private static final jdk.internal.reflect.ReflectionFactory delegate = AccessController.doPrivileged( new PrivilegedAction() { public jdk.internal.reflect.ReflectionFactory run() { return jdk.internal.reflect.ReflectionFactory.getReflectionFactory(); } - }); - } + }); + + private ReflectionFactory() {} private static final Permission REFLECTION_FACTORY_ACCESS_PERM = new RuntimePermission("reflectionFactoryAccess"); @@ -53,7 +63,7 @@ public class ReflectionFactory { * *

First, if there is a security manager, its {@code checkPermission} * method is called with a {@link java.lang.RuntimePermission} with target - * {@code "reflectionFactoryAccess"}. This may result in a securit + * {@code "reflectionFactoryAccess"}. This may result in a security * exception. * *

The returned {@code ReflectionFactory} object should be carefully @@ -61,6 +71,7 @@ public class ReflectionFactory { * data and invoke private methods, as well as to load unverified bytecodes. * It must never be passed to untrusted code. * + * @return the ReflectionFactory * @throws SecurityException if a security manager exists and its * {@code checkPermission} method doesn't allow access to * the RuntimePermission "reflectionFactoryAccess". @@ -73,11 +84,129 @@ public class ReflectionFactory { return soleInstance; } - public Constructor newConstructorForSerialization(Class classToInstantiate, - Constructor constructorToCall) + /** + * Returns an accessible no-arg constructor for a class. + * The no-arg constructor is found searching the class and its supertypes. + * + * @param cl the class to instantiate + * @return a no-arg constructor for the class or {@code null} if + * the class or supertypes do not have a suitable no-arg constructor + */ + public final Constructor newConstructorForSerialization(Class cl) { - return delegate.newConstructorForSerialization(classToInstantiate, - constructorToCall); + return delegate.newConstructorForSerialization(cl); + } + + /** + * Returns an accessible no-arg constructor for an externalizable class to be + * initialized using a public no-argument constructor. + * + * @param cl the class to instantiate + * @return A no-arg constructor for the class; returns {@code null} if + * the class does not implement {@link java.io.Externalizable} + */ + public final Constructor newConstructorForExternalization(Class cl) { + return delegate.newConstructorForExternalization(cl); + } + + /** + * Returns a direct MethodHandle for the {@code readObject} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectInputStream} passed to + * {@code readObject}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code readObject} method of the class or + * {@code null} if the class does not have a {@code readObject} method + */ + public final MethodHandle readObjectForSerialization(Class cl) { + return delegate.readObjectForSerialization(cl); + } + + /** + * Returns a direct MethodHandle for the {@code readObjectNoData} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectInputStream} passed to + * {@code readObjectNoData}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code readObjectNoData} method + * of the class or {@code null} if the class does not have a + * {@code readObjectNoData} method + */ + public final MethodHandle readObjectNoDataForSerialization(Class cl) { + return delegate.readObjectNoDataForSerialization(cl); + } + + /** + * Returns a direct MethodHandle for the {@code writeObject} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectOutputStream} passed to + * {@code writeObject}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code writeObject} method of the class or + * {@code null} if the class does not have a {@code writeObject} method + */ + public final MethodHandle writeObjectForSerialization(Class cl) { + return delegate.writeObjectForSerialization(cl); + } + + /** + * Returns a direct MethodHandle for the {@code readResolve} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code readResolve} method of the class or + * {@code null} if the class does not have a {@code readResolve} method + */ + public final MethodHandle readResolveForSerialization(Class cl) { + return delegate.readResolveForSerialization(cl); + } + + /** + * Returns a direct MethodHandle for the {@code writeReplace} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code writeReplace} method of the class or + * {@code null} if the class does not have a {@code writeReplace} method + */ + public final MethodHandle writeReplaceForSerialization(Class cl) { + return delegate.writeReplaceForSerialization(cl); + } + + /** + * Returns true if the class has a static initializer. + * The presence of a static initializer is used to compute the serialVersionUID. + * @param cl a serializable class + * @return {@code true} if the class has a static initializer, + * otherwise {@code false} + */ + public final boolean hasStaticInitializerForSerialization(Class cl) { + return delegate.hasStaticInitializerForSerialization(cl); + } + + /** + * Returns a new OptionalDataException with {@code eof} set to {@code true} + * or {@code false}. + * @param bool the value of {@code eof} in the created OptionalDataException + * @return a new OptionalDataException + */ + public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) { + Constructor cons = delegate.newOptionalDataExceptionForSerialization(); + try { + return cons.newInstance(bool); + } catch (InstantiationException|IllegalAccessException|InvocationTargetException ex) { + throw new InternalError("unable to create OptionalDataException", ex); + } } } diff --git a/jdk/test/com/oracle/security/ucrypto/TestAES.java b/jdk/test/com/oracle/security/ucrypto/TestAES.java index 4ed48659c86..717e3186d97 100644 --- a/jdk/test/com/oracle/security/ucrypto/TestAES.java +++ b/jdk/test/com/oracle/security/ucrypto/TestAES.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * 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,9 +23,11 @@ /* * @test - * @bug 7088989 8014374 + * @bug 7088989 8014374 8167512 * @summary Ensure the AES ciphers of OracleUcrypto provider works correctly * @key randomness + * @run main TestAES + * @run main/othervm/java.security.policy==empty.policy TestAES */ import java.io.*; diff --git a/jdk/test/com/oracle/security/ucrypto/empty.policy b/jdk/test/com/oracle/security/ucrypto/empty.policy new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java new file mode 100644 index 00000000000..b78605af903 --- /dev/null +++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +import java.rmi.UnexpectedException; + +import javax.rmi.CORBA.Stub; +import javax.rmi.CORBA.Util; + +import org.omg.CORBA.SystemException; +import org.omg.CORBA.portable.ApplicationException; +import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.RemarshalException; +import org.omg.CORBA.portable.ServantObject; + + +/** + * ObjectStreamTest$Echo Stub class generated by rmic, do not edit. + */ +public class ObjectStreamTest$_Echo_Stub extends Stub implements ObjectStreamTest.Echo { + + private static final String[] _type_ids = { + "RMI:ObjectStreamTest\\U0024Echo:0000000000000000" + }; + + private static final long serialVersionUID = 5217577841494640354L; + + public String[] _ids() { + return _type_ids.clone(); + } + + public Object echo(Object arg0) throws java.rmi.RemoteException { + if (!Util.isLocal(this)) { + try { + org.omg.CORBA.portable.InputStream in = null; + try { + OutputStream out = _request("echo", true); + Util.writeAny(out,arg0); + in = _invoke(out); + return Util.readAny(in); + } catch (ApplicationException ex) { + in = ex.getInputStream(); + String $_id = in.read_string(); + throw new UnexpectedException($_id); + } catch (RemarshalException ex) { + return echo(arg0); + } finally { + _releaseReply(in); + } + } catch (SystemException ex) { + throw Util.mapSystemException(ex); + } + } else { + ServantObject so = _servant_preinvoke("echo",ObjectStreamTest.Echo.class); + if (so == null) { + return echo(arg0); + } + try { + Object arg0Copy = Util.copyObject(arg0,_orb()); + Object result = ((ObjectStreamTest.Echo)so.servant).echo(arg0Copy); + return Util.copyObject(result,_orb()); + } catch (Throwable ex) { + Throwable exCopy = (Throwable)Util.copyObject(ex,_orb()); + throw Util.wrapException(exCopy); + } finally { + _servant_postinvoke(so); + } + } + } + } diff --git a/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Server_Tie.java b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Server_Tie.java new file mode 100644 index 00000000000..1b10a99e265 --- /dev/null +++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Server_Tie.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ +import java.rmi.Remote; + +import javax.rmi.CORBA.Tie; +import javax.rmi.CORBA.Util; + +import org.omg.CORBA.BAD_OPERATION; +import org.omg.CORBA.ORB; +import org.omg.CORBA.SystemException; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.ResponseHandler; +import org.omg.CORBA.portable.UnknownException; +import org.omg.CORBA_2_3.portable.ObjectImpl; + + +/** + * ObjectStreamClass$Echo server tie class generated by rmic, do not edit. + */ +public class ObjectStreamTest$_Server_Tie extends ObjectImpl implements Tie { + + volatile private ObjectStreamTest.Server target = null; + + private static final String[] _type_ids = { + "RMI:ObjectStreamTest\\U0024Echo:0000000000000000" + }; + + public void setTarget(Remote target) { + this.target = (ObjectStreamTest.Server) target; + } + + public Remote getTarget() { + return target; + } + + public org.omg.CORBA.Object thisObject() { + return this; + } + + public void deactivate() { + _orb().disconnect(this); + _set_delegate(null); + target = null; + } + + public ORB orb() { + return _orb(); + } + + public void orb(ORB orb) { + orb.connect(this); + } + + public String[] _ids() { + return _type_ids.clone(); + } + + public OutputStream _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException { + try { + ObjectStreamTest.Server target = this.target; + if (target == null) { + throw new java.io.IOException(); + } + org.omg.CORBA_2_3.portable.InputStream in = + (org.omg.CORBA_2_3.portable.InputStream) _in; + if (method.equals("echo")) { + Object arg0 = Util.readAny(in); + Object result = target.echo(arg0); + OutputStream out = reply.createReply(); + Util.writeAny(out,result); + return out; + } + throw new BAD_OPERATION(); + } catch (SystemException ex) { + throw ex; + } catch (Throwable ex) { + throw new UnknownException(ex); + } + } +} diff --git a/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java new file mode 100644 index 00000000000..acfda6042b7 --- /dev/null +++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.Arrays; + +import java.util.EnumSet; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Objects; +import java.util.PropertyPermission; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; + +import javax.naming.CommunicationException; +import javax.naming.InitialContext; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.rmi.CORBA.Util; +import javax.rmi.PortableRemoteObject; + +import org.omg.CORBA_2_3.ORB; +import org.omg.CORBA_2_3.portable.OutputStream; +import org.omg.CORBA_2_3.portable.InputStream; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.JDKToolLauncher; + +import org.testng.Assert; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import org.testng.TestNG; + +/* + * @test + * @library /test/lib + * @build jdk.test.lib.* + * @compile ObjectStreamTest.java ObjectStreamTest$_Echo_Stub.java ObjectStreamTest$_Server_Tie.java + * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io java.corba/com.sun.corba.se.impl.activation + * @summary Tests of ReflectionFactory use in IIOP Serialization + * @run testng/othervm + * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory + * -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest + * @run testng/othervm/policy=security.policy + * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory + * -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest + */ + +@Test +public class ObjectStreamTest { + + enum Colors {RED, GREEN, YELLOW} + + static Set colorSet = new HashSet<>(); + + static { + colorSet.add(Colors.RED); + colorSet.add(Colors.GREEN); + } + + /** + * The process spawned to run orbd. + */ + static Process orbdProcess; + static Thread orbThread; + + @DataProvider(name = "Objects") + static Object[][] patterns() { + BigInteger bigInteger = new BigInteger("8943892002309239"); + InetAddress inetAddr; + try { + inetAddr = java.net.InetAddress.getByAddress(new byte[]{127, 0, 0, 1}); + } catch (UnknownHostException ignored) { + inetAddr = null; + // ignored + } + HashMap hashMap = new HashMap<>(); + hashMap.put("BigInteger", bigInteger); + hashMap.put("InetAddress", inetAddr); + hashMap.put("String", "bString"); + Object[][] patterns = new Object[][]{ + {"aString"}, + {Integer.valueOf(5)}, + {new SimpleObject(4, 4.0f)}, + {Arrays.asList("a", "b", "c")}, + {new String[]{"x", "y", "z"}}, + {new ArrayList(1)}, // uses readObject/writeObject + {new StringBuffer("abc")}, // Has serialPersistentFields + {new StringBuilder("abc")}, + {Colors.RED}, + {inetAddr}, + {LocalTime.MIDNIGHT}, // uses writeReplace/readResolve + {new LongAdder()}, // uses writeReplace/readResolve + {EnumSet.allOf(Colors.class)}, // used writeReplace/readResolve + {bigInteger}, + {new BigDecimal(bigInteger)}, + {hashMap}, + {new PropertyPermission("abc", "read")}, // has serialPersistentFields + }; + return patterns; + } + + + /** + * Check ObjectStreamClass facts match between core serialization and CORBA. + * + * @param value + */ + @Test(dataProvider = "Objects") + static void factCheck(Serializable value) { + Class clazz = value.getClass(); + java.io.ObjectStreamClass sOSC = java.io.ObjectStreamClass.lookup(clazz); + java.io.ObjectStreamField[] sFields = sOSC.getFields(); + com.sun.corba.se.impl.io.ObjectStreamClass cOSC = corbaLookup(clazz); + com.sun.corba.se.impl.io.ObjectStreamField[] cFields = cOSC.getFields(); + + Assert.assertEquals(sFields.length, cFields.length, "Different number of fields"); + for (int i = 0; i < sFields.length; i++) { + Assert.assertEquals(sFields[i].getName(), cFields[i].getName(), "different field names " + cFields[i].getName()); + Assert.assertEquals(sFields[i].getType(), cFields[i].getType(), "different field types " + cFields[i].getName()); + Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(), "different field typestrings " + cFields[i].getName()); + } + + Assert.assertEquals(baseMethod("hasReadObjectMethod", sOSC, (Class[]) null), + corbaMethod("hasReadObject", cOSC, (Class[]) null), "hasReadObject: " + value.getClass()); + + Assert.assertEquals(baseMethod("hasWriteObjectMethod", sOSC, (Class[]) null), + corbaMethod("hasWriteObject", cOSC, (Class[]) null), "hasWriteObject: " + value.getClass()); + + Assert.assertEquals(baseMethod("hasWriteReplaceMethod", sOSC, (Class[]) null), + corbaMethod("hasWriteReplaceMethod", cOSC, (Class[]) null), "hasWriteReplace: " + value.getClass()); + + Assert.assertEquals(baseMethod("hasReadResolveMethod", sOSC, (Class[]) null), + corbaMethod("hasReadResolveMethod", cOSC, (Class[]) null), "hasReadResolve: " + value.getClass()); + + Assert.assertEquals(baseMethod("getSerialVersionUID", sOSC, (Class[]) null), + corbaMethod("getSerialVersionUID", cOSC, (Class[]) null), "getSerialVersionUID: " + value.getClass()); + + } + + + /** + * Test that objects written using Util.writeAny can be serialized + * and deserialized using Util.readAny to equivalent objects. + */ + @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"}) + static void WriteValueObjectStreamTest01(Serializable value) throws Exception { + ORB orb = (ORB) ORB.init(new String[0], null); + + OutputStream out = (OutputStream) orb.create_output_stream(); + Util.writeAny(out, value); + + InputStream in = (InputStream) out.create_input_stream(); + Object actual = Util.readAny(in); + + checkEquals(actual, value); + } + + /** + * Test that objects can be echoed to a server and come back equivalent. + */ + @Test(dataProvider = "Objects", enabled = false, dependsOnMethods = {"factCheck"}) + static void echoObjects(Serializable value) throws Exception { + Context initialNamingContext = Server.init(); + Echo echo = (Echo) PortableRemoteObject.narrow( + initialNamingContext.lookup(Server.serverID), Echo.class); + Object actual = echo.echo(value); + checkEquals(actual, value); + } + + /** + * Check if the value and result are equals, with some tests depending on the type. + * @param expected the expected value + * @param actual the actual value + */ + static void checkEquals(Object actual, Object expected) { + Class cl = expected.getClass(); + Assert.assertEquals(actual.getClass(), cl, "type of value not equal to class of result"); + try { + if (cl.isArray() || !(cl.getDeclaredMethod("equals", cl) == null)) { + Assert.assertEquals(actual, expected, "echo'd object not equal"); + } else { + Assert.assertEquals(toString(actual), toString(expected), "toString values not equal"); + } + } catch (NoSuchMethodException ex) { + Assert.assertEquals(toString(actual), toString(expected), "toString values not equal"); + } + } + + /** + * Convert an object to a String, and correctly for arrays. + * @param obj an object + * @return the tostring for the object. + */ + static String toString(Object obj) { + return obj.getClass().isArray() + ? Arrays.toString((Object[]) obj) + : Objects.toString(obj); + } + + /** + * SimpleObject to test round trip. + */ + static class SimpleObject implements Serializable { + private static final long serialVersionUID = 5217577841494640354L; + + private int i = 0; + private float f = 0.0f; + + SimpleObject(int i, float f) { + this.i = i; + this.f = f; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SimpleObject that = (SimpleObject) o; + + if (i != that.i) return false; + return Float.compare(that.f, f) == 0; + + } + + @Override + public int hashCode() { + int result = i; + result = 31 * result + (f != +0.0f ? Float.floatToIntBits(f) : 0); + return result; + } + + @Override + public String toString() { + return "SimpleObject{" + + "i=" + i + + ", f=" + f + + '}'; + } + } + + + /** + * Lookup the CORBA ObjectStreamClass instance for a class. + * @param clazz the class + * @return the CORBA ObjectStreamClass instance for the class + */ + static com.sun.corba.se.impl.io.ObjectStreamClass corbaLookup(Class clazz) { + Class oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class; + + try { + Method meth = oscClass.getDeclaredMethod("lookup", Class.class); + meth.setAccessible(true); + return (com.sun.corba.se.impl.io.ObjectStreamClass) meth.invoke(null, clazz); + } catch (NoSuchMethodException noMeth) { + throw new RuntimeException("missing method", noMeth); + } catch (IllegalAccessException | InvocationTargetException rex) { + throw new RuntimeException("invocation failed", rex); + } + } + + /** + * Lookup aand invoke method on a serializable object via the CORBA ObjectStreamClass. + * @param methodName method name + * @param osc CORBA ObjectStreamClass + * @param argClasses method arguments + * @return the value returned from invoking the method + */ + static Object corbaMethod(String methodName, com.sun.corba.se.impl.io.ObjectStreamClass osc, Class... argClasses) { + Class oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class; + + try { + Method meth = oscClass.getDeclaredMethod(methodName, argClasses); + meth.setAccessible(true); + return meth.invoke(osc); + + } catch (NoSuchMethodException noMeth) { + throw new RuntimeException("missing method" + osc.getName() + + "::" + methodName, noMeth); + } catch (IllegalAccessException | InvocationTargetException rex) { + throw new RuntimeException("invocation failed", rex); + } + } + + + /** + * Lookup aand invoke method on a serializable object via java.io.ObjectStreamClass. + * @param methodName method name + * @param osc java.io.ObjectStreamClass + * @param argClasses method arguments + * @return the value returned from invoking the method + */ + static Object baseMethod(String methodName, java.io.ObjectStreamClass osc, Class... argClasses) { + Class oscClass = java.io.ObjectStreamClass.class; + + try { + Method meth = oscClass.getDeclaredMethod(methodName, argClasses); + meth.setAccessible(true); + return meth.invoke(osc); + + } catch (NoSuchMethodException noMeth) { + throw new RuntimeException("missing method: " + osc.getName() + + "::" + methodName, noMeth); + } catch (IllegalAccessException | InvocationTargetException rex) { + throw new RuntimeException("invocation failed", rex); + } + } + + /** + * Simple echo interface to check serialization/deserialization. + */ + interface Echo extends Remote { + Object echo(Object obj) throws RemoteException; + } + + static class Server extends PortableRemoteObject implements Echo { + + public static final String serverID = "ObjectStreamTestServer"; + + private static Context initialNamingContext; + + private static Server server; + + public Server() throws RemoteException { + super(); + } + + public Object echo(Object obj) { + return obj; + } + + + public static Context init() { + if (initialNamingContext == null) { + try { + startOrbd(); + Thread.sleep(5000L); // Give it 5 seconds + } catch (Exception eex) { + throw new RuntimeException("Orbd", eex); + } + for (int i = 0; i < 1; i++) { + try { + Thread.sleep(1L); + initialNamingContext = new InitialContext(); + server = new Server(); + initialNamingContext.rebind(serverID, server); + } catch (CommunicationException | InterruptedException cex) { + System.out.printf("retry #%d sec: ex: %s%n", i, cex); + } catch (NamingException ex) { + throw new RuntimeException("can't initialize naming context", ex); + } catch (RemoteException rex) { + throw new RuntimeException("can't initialize server", rex); + } + } + } + if (initialNamingContext == null) { + Assert.fail("Can't initialize the Orb, no naming context"); + } + return initialNamingContext; + } + } + + static void startOrbd() throws Exception { + System.out.println("\nStarting orbd with NS port 1050 "); + JDKToolLauncher orbdLauncher = JDKToolLauncher.create("orbd") + .addToolArg("-ORBInitialHost").addToolArg("localhost") + .addToolArg("-ORBInitialPort").addToolArg("1050"); + + System.out.println("ObjectStreamTest: Executing: " + Arrays.asList(orbdLauncher.getCommand())); + ProcessBuilder pb = new ProcessBuilder(orbdLauncher.getCommand()); + + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + orbdProcess = pb.start(); + } + + @AfterSuite + static void killOrbd() throws Exception { + if (orbdProcess != null) { + orbdProcess.destroyForcibly(); + orbdProcess.waitFor(); + System.out.printf("destroyed orbd, pid: %d, exitValue: %d%n", + orbdProcess.getPid(), orbdProcess.exitValue()); + } + } + + + + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + @Test(enabled = false) + public static void main(String[] args) { + Class[] testclass = {ObjectStreamTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } + +} diff --git a/jdk/test/com/sun/corba/serialization/security.policy b/jdk/test/com/sun/corba/serialization/security.policy new file mode 100644 index 00000000000..ec31368a25c --- /dev/null +++ b/jdk/test/com/sun/corba/serialization/security.policy @@ -0,0 +1,15 @@ +// Individual Permissions for ObjectStreamTest +grant { + // Permissions needed to run the test + permission java.util.PropertyPermission "*", "read"; + permission java.io.FilePermission "<>", "read,write,delete,execute"; + permission java.net.SocketPermission "*", "resolve,connect,listen,accept"; + + // Permissions to allow ObjectTest to use IIOP ObjectStreamClass + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.corba.se.impl.io"; + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.misc"; + permission java.io.SerializablePermission "enableSubclassImplementation"; +}; diff --git a/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java b/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java index 92a71e9c089..1da73b02695 100644 --- a/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java +++ b/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java @@ -28,6 +28,7 @@ import java.security.AccessControlException; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import org.testng.Assert; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @@ -65,20 +66,21 @@ public class FilterWithSecurityManagerTest { */ @Test public void testGlobalFilter() throws Exception { - if (ObjectInputFilter.Config.getSerialFilter() == null) { - return; - } - try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter(); + + try { ObjectInputFilter.Config.setSerialFilter(filter); assertFalse(setSecurityManager, "When SecurityManager exists, without " - + "java.security.SerializablePermission(serialFilter) Exception should be thrown"); - Object o = ois.readObject(); + + "java.io.SerializablePermission(serialFilter) " + + "IllegalStateException should be thrown"); } catch (AccessControlException ex) { assertTrue(setSecurityManager); assertTrue(ex.getMessage().contains("java.io.SerializablePermission")); assertTrue(ex.getMessage().contains("serialFilter")); + } catch (IllegalStateException ise) { + // ISE should occur only if global filter already set + Assert.assertNotNull(global, "Global filter should be non-null"); } } diff --git a/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java b/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java index 60aab3c5ea0..d9c02c84210 100644 --- a/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java +++ b/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java @@ -126,9 +126,7 @@ public class GlobalFilterTest { ObjectInputFilter.Config.setSerialFilter(filter); Assert.fail("set only once process-wide filter"); } catch (IllegalStateException ise) { - if (sm != null) { - Assert.fail("wrong exception when security manager is set", ise); - } + // Normal, once set can never be re-set even if no security manager } catch (SecurityException se) { if (sm == null) { Assert.fail("wrong exception when security manager is not set", se); diff --git a/jdk/test/java/io/Serializable/serialFilter/security.policy b/jdk/test/java/io/Serializable/serialFilter/security.policy index 3b4d21b7b8f..446ee4d85db 100644 --- a/jdk/test/java/io/Serializable/serialFilter/security.policy +++ b/jdk/test/java/io/Serializable/serialFilter/security.policy @@ -1,7 +1,8 @@ -// Individual Permissions to for GlobalFilterTest +// Individual Permissions to for GlobalFilterTest and FilterWithSecurityManager grant { // Specific permission under test - permission java.security.SerializablePermission "serialFilter"; + permission java.io.SerializablePermission "serialFilter"; + // Permissions needed to run the test permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "<>", "read,write,delete"; diff --git a/jdk/test/java/lang/StackWalker/CallerSensitiveMethod/Main.java b/jdk/test/java/lang/StackWalker/CallerSensitiveMethod/Main.java index 8dc52c45d98..6769f6d3355 100644 --- a/jdk/test/java/lang/StackWalker/CallerSensitiveMethod/Main.java +++ b/jdk/test/java/lang/StackWalker/CallerSensitiveMethod/Main.java @@ -26,6 +26,7 @@ * @bug 8157464 * @summary Basic test for StackWalker.getCallerClass() * @library src + * @modules java.base/jdk.internal.reflect * @build java.base/java.util.CSM csm/* * @run main/othervm csm/jdk.test.CallerSensitiveTest * @run main/othervm csm/jdk.test.CallerSensitiveTest sm diff --git a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java index cdeb61b899a..139a56871b9 100644 --- a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java +++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java @@ -25,8 +25,8 @@ * @test * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jmod * jdk.compiler + * jdk.jlink * @build ModuleReaderTest CompilerUtils JarUtils * @run testng ModuleReaderTest * @summary Basic tests for java.lang.module.ModuleReader @@ -48,6 +48,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Optional; +import java.util.spi.ToolProvider; import jdk.internal.module.ConfigurableModuleFinder; import jdk.internal.module.ConfigurableModuleFinder.Phase; @@ -196,8 +197,11 @@ public class ModuleReaderTest { String cp = MODS_DIR.resolve(TEST_MODULE).toString(); String jmod = dir.resolve("m.jmod").toString(); String[] args = { "create", "--class-path", cp, jmod }; - jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask(); - assertEquals(task.run(args), 0); + ToolProvider jmodTool = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + assertEquals(jmodTool.run(System.out, System.out, args), 0); test(dir); } diff --git a/jdk/test/java/lang/reflect/AccessControl/AccessControlTest.java b/jdk/test/java/lang/reflect/AccessControl/AccessControlTest.java new file mode 100644 index 00000000000..aa4d58add0c --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/AccessControlTest.java @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 util.ClassSupplier; +import util.MemberFactory; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toCollection; +import static util.MemberFactory.*; +import static util.MemberFactory.Group.*; +import static util.ClassSupplier.*; + +/** + * @test + * @summary An exhaustive test of reflective access controls + * @bug 6378384 + * @build a.PublicSuper a.Package b.PublicSub b.Package + * util.MemberFactory util.ClassSupplier + * @run main AccessControlTest + */ +public class AccessControlTest { + + public static void main(String[] args) throws Exception { + boolean ok = true; + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_A) + .member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A) + .allowed(ALL) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_A) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A) + .allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_A) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_A) + .member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B) + .denied (ALL) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_A) + .member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUPERCLASS_IN_PKG_A) + .member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A) + .allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUPERCLASS_IN_PKG_A) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A) + .allowed(ALL) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUPERCLASS_IN_PKG_A) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(ALL) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUPERCLASS_IN_PKG_A) + .member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B) + .denied (ALL) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUPERCLASS_IN_PKG_A) + .member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_B) + .member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A) + .denied (ALL) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_B) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A) + .allowed(PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_B) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_MEMBERS) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_B) + .member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B) + .allowed(ALL) + .perform(); + + ok &= new Test() + .current(PACKAGE_CLASS_IN_PKG_B) + .member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUBCLASS_IN_PKG_B) + .member (PACKAGE_CLASS_IN_PKG_A).target(PACKAGE_CLASS_IN_PKG_A) + .denied (ALL) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUBCLASS_IN_PKG_B) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUPERCLASS_IN_PKG_A) + .allowed(PUBLIC_MEMBERS, PROTECTED_STATIC_F_M) + .denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_INSTANCE_F_M, + PROTECTED_C) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUBCLASS_IN_PKG_B) + .member (PUBLIC_SUPERCLASS_IN_PKG_A).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(PUBLIC_MEMBERS, PROTECTED_INSTANCE_F_M, PROTECTED_STATIC_F_M) + .denied (PRIVATE_MEMBERS, PACKAGE_MEMBERS, PROTECTED_C) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUBCLASS_IN_PKG_B) + .member (PACKAGE_CLASS_IN_PKG_B).target(PACKAGE_CLASS_IN_PKG_B) + .allowed(PACKAGE_MEMBERS, PROTECTED_MEMBERS, PUBLIC_MEMBERS) + .denied (PRIVATE_MEMBERS) + .perform(); + + ok &= new Test() + .current(PUBLIC_SUBCLASS_IN_PKG_B) + .member (PUBLIC_SUBCLASS_IN_PKG_B).target(PUBLIC_SUBCLASS_IN_PKG_B) + .allowed(ALL) + .perform(); + + if (ok) { + System.out.println("\nAll cases passed."); + } else { + throw new RuntimeException("Some cases failed - see log."); + } + } + + // use this for generating an exhaustive set of test cases on stdout + public static class Generate { + public static void main(String[] args) { + for (ClassSupplier current : ClassSupplier.values()) { + for (ClassSupplier member : ClassSupplier.values()) { + for (ClassSupplier target : ClassSupplier.values()) { + if (member.get().isAssignableFrom(target.get())) { + new Test() + .current(current).member(member).target(target) + .allowed(ALL) + .perform(true); + } + } + } + } + } + } + + static class Test { + + ClassSupplier currentClassSupplier, memberClassSupplier, targetClassSupplier; + EnumSet expectAllowedMembers = EnumSet.noneOf(MemberFactory.class); + EnumSet expectDeniedMembers = EnumSet.noneOf(MemberFactory.class); + + Test current(ClassSupplier current) { + currentClassSupplier = current; + return this; + } + + Test member(ClassSupplier member) { + memberClassSupplier = member; + return this; + } + + Test target(ClassSupplier target) { + targetClassSupplier = target; + return this; + } + + Test allowed(MemberFactory... allowed) { + expectAllowedMembers = MemberFactory.asSet(allowed); + return this; + } + + Test allowed(MemberFactory.Group... allowedGroups) { + expectAllowedMembers = MemberFactory.groupsToMembers( + MemberFactory.Group.asSet(allowedGroups)); + return this; + } + + Test denied(MemberFactory... denied) { + expectDeniedMembers = MemberFactory.asSet(denied); + return this; + } + + Test denied(MemberFactory.Group... deniedGroups) { + expectDeniedMembers = MemberFactory.groupsToMembers( + MemberFactory.Group.asSet(deniedGroups)); + return this; + } + + boolean perform() { + return perform(false); + } + + boolean perform(boolean generateCases) { + + // some validation 1st + EnumSet intersection = EnumSet.copyOf(expectAllowedMembers); + intersection.retainAll(expectDeniedMembers); + if (!intersection.isEmpty()) { + throw new IllegalArgumentException( + "Expected allowed and denied MemberFactories have non-empty intersection: " + + intersection); + } + + EnumSet missing = EnumSet.allOf(MemberFactory.class); + missing.removeAll(expectAllowedMembers); + missing.removeAll(expectDeniedMembers); + if (!missing.isEmpty()) { + throw new IllegalArgumentException( + "Union of expected allowed and denied MemberFactories is missing elements: " + + missing); + } + + // retrieve method that will perform reflective access + Method checkAccessMethod; + try { + checkAccessMethod = currentClassSupplier.get().getDeclaredMethod( + "checkAccess", AccessibleObject.class, Object.class); + // in case of inaccessible currentClass + checkAccessMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + + // construct a target object (for instance field/method) + Object target; + Constructor targetConstructor = + (Constructor) PUBLIC_CONSTRUCTOR.apply(targetClassSupplier.get()); + // in case of inaccessible targetClass + targetConstructor.setAccessible(true); + try { + target = targetConstructor.newInstance( + new Object[targetConstructor.getParameterCount()]); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + + Class memberClass = memberClassSupplier.get(); + + Map> actualMembers = Stream.concat( + + expectAllowedMembers.stream().map(member -> new Trial(member, true)), + expectDeniedMembers.stream().map(member -> new Trial(member, false)) + + ).map(trial -> { + + // obtain AccessibleObject to be used to perform reflective access + AccessibleObject accessibleObject = trial.member.apply(memberClass); + + // only need target 'obj' for instance fields and methods + Object obj = + (accessibleObject instanceof Field && + !Modifier.isStatic(((Field) accessibleObject).getModifiers()) + || + accessibleObject instanceof Method && + !Modifier.isStatic(((Method) accessibleObject).getModifiers()) + ) + ? target : null; + + // invoke checkAccess method and let it perform the reflective access + try { + checkAccessMethod.invoke(null, accessibleObject, obj); + trial.actualAllowed = true; + } catch (IllegalAccessException e) { + // should not happen as checkAccessMethod.isAccessible() + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof IllegalAccessException) { + trial.actualAllowed = false; + } else { + // any other Exception is a fault in test or infrastructure - fail fast + throw new RuntimeException(e.getTargetException()); + } + } + + if (!generateCases) { + System.out.printf( + "%-26s accessing %26s's %-25s %-43s - expected %s, actual %s: %s\n", + currentClassSupplier, memberClassSupplier, trial.member.name(), + (obj == null ? "" : "with instance of " + targetClassSupplier), + (trial.expectAllowed ? "allowed" : "denied "), + (trial.actualAllowed ? "allowed" : "denied "), + (trial.expectAllowed == trial.actualAllowed ? "OK" : "FAILURE") + ); + } + + return trial; + + }).collect( + groupingBy( + Trial::isActualAllowed, + mapping( + Trial::getMember, + toCollection(() -> EnumSet.noneOf(MemberFactory.class)))) + ); + + EnumSet actualAllowedMembers = + Optional.ofNullable(actualMembers.get(true)) + .orElse(EnumSet.noneOf(MemberFactory.class)); + EnumSet actualDeniedMembers = + Optional.ofNullable(actualMembers.get(false)) + .orElse(EnumSet.noneOf(MemberFactory.class)); + + if (generateCases) { + System.out.printf( + " ok &= new Test()\n" + + " .current(%s)\n" + + " .member (%s).target(%s)\n", + currentClassSupplier, + memberClassSupplier, targetClassSupplier + ); + + if (!actualAllowedMembers.isEmpty()) { + EnumSet actualAllowed = + MemberFactory.membersToGroupsOrNull(actualAllowedMembers); + if (actualAllowed == null) + actualAllowed = actualAllowedMembers; + System.out.print( + chunkBy(3, actualAllowed.stream().map(Enum::name)) + .map(chunk -> chunk.collect(joining(", "))) + .collect(joining(",\n" + + " ", + " .allowed(", + ")\n")) + ); + } + + if (!actualDeniedMembers.isEmpty()) { + EnumSet actualDenied = + MemberFactory.membersToGroupsOrNull(actualDeniedMembers); + if (actualDenied == null) + actualDenied = actualAllowedMembers; + System.out.print( + chunkBy(3, actualDenied.stream().map(Enum::name)) + .map(chunk -> chunk.collect(joining(", "))) + .collect(joining(",\n" + + " ", + " .denied (", + ")\n")) + ); + } + + System.out.print( + " .perform();\n" + ); + } + + return expectAllowedMembers.equals(actualAllowedMembers) && + expectDeniedMembers.equals(actualDeniedMembers); + } + } + + private static Stream> chunkBy(int chunkSize, Stream stream) { + Iterator elements = stream.iterator(); + Stream.Builder> b1 = Stream.builder(); + while (elements.hasNext()) { + Stream.Builder b2 = Stream.builder(); + for (int i = 0; i < chunkSize && elements.hasNext(); i++) { + b2.accept(elements.next()); + } + b1.accept(b2.build()); + } + return b1.build(); + } + + private static class Trial { + final MemberFactory member; + final boolean expectAllowed; + boolean actualAllowed; + + Trial(MemberFactory member, boolean expectAllowed) { + this.member = member; + this.expectAllowed = expectAllowed; + } + + MemberFactory getMember() { + return member; + } + + boolean isActualAllowed() { + return actualAllowed; + } + } +} diff --git a/jdk/test/java/lang/reflect/AccessControl/a/Package.java b/jdk/test/java/lang/reflect/AccessControl/a/Package.java new file mode 100644 index 00000000000..9b5632b815f --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/a/Package.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 a; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A package-private class in a. + */ +class Package { + + // fields + private static int privateStatic; + private int privateInstance; + static int packageStatic; + int packageInstance; + protected static int protectedStatic; + protected int protectedInstance; + public static int publicStatic; + public int publicInstance; + + // methods + private static int privateStatic() { return 42; } + private int privateInstance() { return 42; } + static int packageStatic() { return 42; } + int packageInstance() { return 42; } + protected static int protectedStatic() { return 42; } + protected int protectedInstance() { return 42; } + public static int publicStatic() { return 42; } + public int publicInstance() { return 42; } + + // constructors + private Package(Void _1, Void _2, Void _3) {} + Package(Void _1, Void _2) {} + protected Package(Void _1) {} + public Package() {} + + + // testing method + public static void checkAccess(AccessibleObject accessibleObject, Object obj) + throws IllegalAccessException, + InvocationTargetException, + InstantiationException + { + if (accessibleObject instanceof Field) { + Field field = (Field) accessibleObject; + field.set(obj, 42); + field.get(obj); + } else if (accessibleObject instanceof Method) { + Method method = (Method) accessibleObject; + method.invoke(obj); + } else if (accessibleObject instanceof Constructor) { + Constructor constructor = (Constructor) accessibleObject; + Object[] params = new Object[constructor.getParameterCount()]; + constructor.newInstance(params); + } + } +} diff --git a/jdk/test/java/lang/reflect/AccessControl/a/PublicSuper.java b/jdk/test/java/lang/reflect/AccessControl/a/PublicSuper.java new file mode 100644 index 00000000000..ecec03d6e0f --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/a/PublicSuper.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 a; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A public class in a which is a superclass of public class in b. + */ +public class PublicSuper { + + // fields + private static int privateStatic; + private int privateInstance; + static int packageStatic; + int packageInstance; + protected static int protectedStatic; + protected int protectedInstance; + public static int publicStatic; + public int publicInstance; + + // methods + private static int privateStatic() { return 42; } + private int privateInstance() { return 42; } + static int packageStatic() { return 42; } + int packageInstance() { return 42; } + protected static int protectedStatic() { return 42; } + protected int protectedInstance() { return 42; } + public static int publicStatic() { return 42; } + public int publicInstance() { return 42; } + + // constructors + private PublicSuper(Void _1, Void _2, Void _3) {} + PublicSuper(Void _1, Void _2) {} + protected PublicSuper(Void _1) {} + public PublicSuper() {} + + + // testing method + public static void checkAccess(AccessibleObject accessibleObject, Object obj) + throws IllegalAccessException, + InvocationTargetException, + InstantiationException + { + if (accessibleObject instanceof Field) { + Field field = (Field) accessibleObject; + field.set(obj, 42); + field.get(obj); + } else if (accessibleObject instanceof Method) { + Method method = (Method) accessibleObject; + method.invoke(obj); + } else if (accessibleObject instanceof Constructor) { + Constructor constructor = (Constructor) accessibleObject; + Object[] params = new Object[constructor.getParameterCount()]; + constructor.newInstance(params); + } + } +} diff --git a/jdk/test/java/lang/reflect/AccessControl/b/Package.java b/jdk/test/java/lang/reflect/AccessControl/b/Package.java new file mode 100644 index 00000000000..6c14d882178 --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/b/Package.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 b; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A package-private class in b. + */ +class Package { + + // fields + private static int privateStatic; + private int privateInstance; + static int packageStatic; + int packageInstance; + protected static int protectedStatic; + protected int protectedInstance; + public static int publicStatic; + public int publicInstance; + + // methods + private static int privateStatic() { return 42; } + private int privateInstance() { return 42; } + static int packageStatic() { return 42; } + int packageInstance() { return 42; } + protected static int protectedStatic() { return 42; } + protected int protectedInstance() { return 42; } + public static int publicStatic() { return 42; } + public int publicInstance() { return 42; } + + // constructors + private Package(Void _1, Void _2, Void _3) {} + Package(Void _1, Void _2) {} + protected Package(Void _1) {} + public Package() {} + + + // testing method + public static void checkAccess(AccessibleObject accessibleObject, Object obj) + throws IllegalAccessException, + InvocationTargetException, + InstantiationException + { + if (accessibleObject instanceof Field) { + Field field = (Field) accessibleObject; + field.set(obj, 42); + field.get(obj); + } else if (accessibleObject instanceof Method) { + Method method = (Method) accessibleObject; + method.invoke(obj); + } else if (accessibleObject instanceof Constructor) { + Constructor constructor = (Constructor) accessibleObject; + Object[] params = new Object[constructor.getParameterCount()]; + constructor.newInstance(params); + } + } +} diff --git a/jdk/test/java/lang/reflect/AccessControl/b/PublicSub.java b/jdk/test/java/lang/reflect/AccessControl/b/PublicSub.java new file mode 100644 index 00000000000..8e8e7a2564a --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/b/PublicSub.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 b; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A public class in b which is a subclass of public class in a. + */ +public class PublicSub extends a.PublicSuper { + + // fields + private static int privateStatic; + private int privateInstance; + static int packageStatic; + int packageInstance; + protected static int protectedStatic; + protected int protectedInstance; + public static int publicStatic; + public int publicInstance; + + // methods + private static int privateStatic() { return 42; } + private int privateInstance() { return 42; } + static int packageStatic() { return 42; } + int packageInstance() { return 42; } + protected static int protectedStatic() { return 42; } + protected int protectedInstance() { return 42; } + public static int publicStatic() { return 42; } + public int publicInstance() { return 42; } + + // constructors + private PublicSub(Void _1, Void _2, Void _3) {} + PublicSub(Void _1, Void _2) {} + protected PublicSub(Void _1) {} + public PublicSub() {} + + + // testing method + public static void checkAccess(AccessibleObject accessibleObject, Object obj) + throws IllegalAccessException, + InvocationTargetException, + InstantiationException + { + if (accessibleObject instanceof Field) { + Field field = (Field) accessibleObject; + field.set(obj, 42); + field.get(obj); + } else if (accessibleObject instanceof Method) { + Method method = (Method) accessibleObject; + method.invoke(obj); + } else if (accessibleObject instanceof Constructor) { + Constructor constructor = (Constructor) accessibleObject; + Object[] params = new Object[constructor.getParameterCount()]; + constructor.newInstance(params); + } + } +} diff --git a/jdk/test/java/lang/reflect/AccessControl/util/ClassSupplier.java b/jdk/test/java/lang/reflect/AccessControl/util/ClassSupplier.java new file mode 100644 index 00000000000..e7ecf3c5c24 --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/util/ClassSupplier.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 util; + +import java.util.function.Supplier; + +/** + * An enumeration of suppliers of test classes. + */ +public enum ClassSupplier implements Supplier> { + PACKAGE_CLASS_IN_PKG_A("a.Package"), + PUBLIC_SUPERCLASS_IN_PKG_A("a.PublicSuper"), + PACKAGE_CLASS_IN_PKG_B("b.Package"), + PUBLIC_SUBCLASS_IN_PKG_B("b.PublicSub"); + + private final String className; + + ClassSupplier(String className) { + this.className = className; + } + + @Override + public Class get() { + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + throw (Error) new NoClassDefFoundError(className).initCause(e); + } + } +} diff --git a/jdk/test/java/lang/reflect/AccessControl/util/MemberFactory.java b/jdk/test/java/lang/reflect/AccessControl/util/MemberFactory.java new file mode 100644 index 00000000000..c960bd87139 --- /dev/null +++ b/jdk/test/java/lang/reflect/AccessControl/util/MemberFactory.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 util; + +import java.lang.reflect.AccessibleObject; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.function.BiFunction; +import java.util.function.Function; + +import static util.MemberFactory.Kind.CONSTRUCTOR; +import static util.MemberFactory.Kind.FIELD; +import static util.MemberFactory.Kind.METHOD; + +/** + * Enumeration of: + *

+ * {private, package, protected, public} x {instance, static} x {field, method} + *

+ * and: + *

+ * {private, package, protected, public} x {constructor}, + *

+ * with each element acting as a factory of AccessibleObject(s) + * declared by given declaringClass(es). + */ +public enum MemberFactory implements Function, AccessibleObject> { + // instance fields + PRIVATE_INSTANCE_FIELD(FIELD, "privateInstance"), + PACKAGE_INSTANCE_FIELD(FIELD, "packageInstance"), + PROTECTED_INSTANCE_FIELD(FIELD, "protectedInstance"), + PUBLIC_INSTANCE_FIELD(FIELD, "publicInstance"), + // instance methods + PRIVATE_INSTANCE_METHOD(METHOD, "privateInstance"), + PACKAGE_INSTANCE_METHOD(METHOD, "packageInstance"), + PROTECTED_INSTANCE_METHOD(METHOD, "protectedInstance"), + PUBLIC_INSTANCE_METHOD(METHOD, "publicInstance"), + // static fields + PRIVATE_STATIC_FIELD(FIELD, "privateStatic"), + PACKAGE_STATIC_FIELD(FIELD, "packageStatic"), + PROTECTED_STATIC_FIELD(FIELD, "protectedStatic"), + PUBLIC_STATIC_FIELD(FIELD, "publicStatic"), + // static methods + PRIVATE_STATIC_METHOD(METHOD, "privateStatic"), + PACKAGE_STATIC_METHOD(METHOD, "packageStatic"), + PROTECTED_STATIC_METHOD(METHOD, "protectedStatic"), + PUBLIC_STATIC_METHOD(METHOD, "publicStatic"), + // constructors + PRIVATE_CONSTRUCTOR(CONSTRUCTOR, null, Void.class, Void.class, Void.class), + PACKAGE_CONSTRUCTOR(CONSTRUCTOR, null, Void.class, Void.class), + PROTECTED_CONSTRUCTOR(CONSTRUCTOR, null, Void.class), + PUBLIC_CONSTRUCTOR(CONSTRUCTOR, null),; + + final Kind kind; + final String name; + final Class[] parameterTypes; + + MemberFactory(Kind kind, String name, Class... parameterTypes) { + this.kind = kind; + this.name = name; + this.parameterTypes = parameterTypes; + } + + @Override + public AccessibleObject apply(Class declaringClass) { + return kind.apply(declaringClass, this); + } + + public static EnumSet asSet(MemberFactory... members) { + return members.length == 0 ? EnumSet.noneOf(MemberFactory.class) + : EnumSet.copyOf(Arrays.asList(members)); + } + + /** + * @param members the set of MemberFactory(s) to convert to set of + * MemberFactory.Group(s). + * @return a set of groups that cover all elements of the members set if + * such set of groups exists or null if it doesn't. + */ + public static EnumSet membersToGroupsOrNull(EnumSet members) { + EnumSet mSet = members.clone(); + EnumSet gSet = EnumSet.allOf(Group.class); + Iterator gIter = gSet.iterator(); + while (gIter.hasNext()) { + Group g = gIter.next(); + if (mSet.containsAll(g.members)) { + mSet.removeAll(g.members); + } else { + gIter.remove(); + } + } + return mSet.isEmpty() ? gSet : null; + } + + /** + * @param groups the set of MemberFactory.Group(s) to convert to set of + * MemberFactory(s). + * @return a set of members as a union of members of all groups. + */ + public static EnumSet groupsToMembers(EnumSet groups) { + EnumSet mSet = EnumSet.noneOf(MemberFactory.class); + for (Group g : groups) { + mSet.addAll(g.members); + } + return mSet; + } + + enum Kind implements BiFunction, MemberFactory, AccessibleObject> { + FIELD { + @Override + public AccessibleObject apply(Class declaringClass, MemberFactory factory) { + assert factory.kind == this; + try { + return declaringClass.getDeclaredField(factory.name); + } catch (NoSuchFieldException e) { + // a fault in test - fail fast + throw new RuntimeException(e.getMessage()); + } + } + }, + METHOD { + @Override + public AccessibleObject apply(Class declaringClass, MemberFactory factory) { + assert factory.kind == this; + try { + return declaringClass.getDeclaredMethod(factory.name, factory.parameterTypes); + } catch (NoSuchMethodException e) { + // a fault in test - fail fast + throw new RuntimeException(e.getMessage()); + } + } + }, + CONSTRUCTOR { + @Override + public AccessibleObject apply(Class declaringClass, MemberFactory factory) { + assert factory.kind == this; + try { + return declaringClass.getDeclaredConstructor(factory.parameterTypes); + } catch (NoSuchMethodException e) { + // a fault in test - fail fast + throw new RuntimeException(e.getMessage()); + } + } + } + } + + /** + * We define groups of MemberFactory(s) for members that commonly + * exhibit same access restrictions in various cases in order to allow + * specifying groups instead of individual members in the test cases, + * making them less verbose. + */ + public enum Group { + // all members + ALL(MemberFactory.values()), + // all private members + PRIVATE_MEMBERS(PRIVATE_INSTANCE_FIELD, PRIVATE_INSTANCE_METHOD, + PRIVATE_STATIC_FIELD, PRIVATE_STATIC_METHOD, + PRIVATE_CONSTRUCTOR), + // all package members + PACKAGE_MEMBERS(PACKAGE_INSTANCE_FIELD, PACKAGE_INSTANCE_METHOD, + PACKAGE_STATIC_FIELD, PACKAGE_STATIC_METHOD, + PACKAGE_CONSTRUCTOR), + // all protected members + PROTECTED_MEMBERS(PROTECTED_INSTANCE_FIELD, PROTECTED_INSTANCE_METHOD, + PROTECTED_STATIC_FIELD, PROTECTED_STATIC_METHOD, + PROTECTED_CONSTRUCTOR), + // all public members + PUBLIC_MEMBERS(PUBLIC_INSTANCE_FIELD, PUBLIC_INSTANCE_METHOD, + PUBLIC_STATIC_FIELD, PUBLIC_STATIC_METHOD, + PUBLIC_CONSTRUCTOR), + // instance field and method pairs + PRIVATE_INSTANCE_F_M(PRIVATE_INSTANCE_FIELD, PRIVATE_INSTANCE_METHOD), + PACKAGE_INSTANCE_F_M(PACKAGE_INSTANCE_FIELD, PACKAGE_INSTANCE_METHOD), + PROTECTED_INSTANCE_F_M(PROTECTED_INSTANCE_FIELD, PROTECTED_INSTANCE_METHOD), + PUBLIC_INSTANCE_F_M(PUBLIC_INSTANCE_FIELD, PUBLIC_INSTANCE_METHOD), + // static field and method pairs + PRIVATE_STATIC_F_M(PRIVATE_STATIC_FIELD, PRIVATE_STATIC_METHOD), + PACKAGE_STATIC_F_M(PACKAGE_STATIC_FIELD, PACKAGE_STATIC_METHOD), + PROTECTED_STATIC_F_M(PROTECTED_STATIC_FIELD, PROTECTED_STATIC_METHOD), + PUBLIC_STATIC_F_M(PUBLIC_STATIC_FIELD, PUBLIC_STATIC_METHOD), + // constructor singles + PRIVATE_C(PRIVATE_CONSTRUCTOR), + PACKAGE_C(PACKAGE_CONSTRUCTOR), + PROTECTED_C(PROTECTED_CONSTRUCTOR), + PUBLIC_C(PUBLIC_CONSTRUCTOR); + + final EnumSet members; + + Group(MemberFactory... members) { + this.members = EnumSet.copyOf(Arrays.asList(members)); + } + + public static EnumSet asSet(Group... groups) { + return groups.length == 0 ? EnumSet.noneOf(Group.class) + : EnumSet.copyOf(Arrays.asList(groups)); + } + } +} diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/serialFilter/FilterUROTest.java b/jdk/test/java/rmi/server/UnicastRemoteObject/serialFilter/FilterUROTest.java new file mode 100644 index 00000000000..c5e73b95e03 --- /dev/null +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/serialFilter/FilterUROTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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.InvalidClassException; +import java.io.ObjectInputFilter; +import java.io.Serializable; + +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.UnmarshalException; +import java.rmi.server.UnicastRemoteObject; + +import java.util.Objects; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/* + * @test + * @run testng/othervm FilterUROTest + * @summary Check that objects are exported with ObjectInputFilters via UnicastRemoteObject + */ +public class FilterUROTest { + + /** + * Data to test serialFilter call counts. + * - name + * - Object + * - expected count of calls to checkInput. + * + * @return array of test data + */ + @DataProvider(name = "bindData") + static Object[][] bindObjects() { + Object[][] data = { + {"SimpleString", "SimpleString", 0}, + {"String", new XX("now is the time"), 1}, + {"String[]", new XX(new String[3]), 3}, + {"Long[4]", new XX(new Long[4]), 3}, + {"RejectME", new XX(new RejectME()), -1}, + }; + return data; + } + + /* + * Test exporting an object with a serialFilter using exportObject(). + * Send some objects and check the number of calls to the serialFilter. + */ + @Test(dataProvider = "bindData") + public void useExportObject(String name, Object obj, int expectedFilterCount) throws RemoteException { + try { + RemoteImpl impl = RemoteImpl.create(); + Echo client = (Echo) UnicastRemoteObject + .exportObject(impl, 0, impl.checker); + int count = client.filterCount(obj); + System.out.printf("count: %d, obj: %s%n", count, obj); + Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); + } catch (RemoteException rex) { + if (expectedFilterCount == -1 && + UnmarshalException.class.equals(rex.getCause().getClass()) && + InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { + return; // normal expected exception + } + rex.printStackTrace(); + Assert.fail("unexpected remote exception", rex); + } catch (Exception rex) { + Assert.fail("unexpected exception", rex); + } + } + + /* + * Test exporting an object with a serialFilter using exportObject() + * with explicit (but null) SocketFactories. + * Send some objects and check the number of calls to the serialFilter. + */ + @Test(dataProvider = "bindData") + public void useExportObject2(String name, Object obj, int expectedFilterCount) throws RemoteException { + try { + RemoteImpl impl = RemoteImpl.create(); + Echo client = (Echo) UnicastRemoteObject + .exportObject(impl, 0, null, null, impl.checker); + int count = client.filterCount(obj); + System.out.printf("count: %d, obj: %s%n", count, obj); + Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); + } catch (RemoteException rex) { + if (expectedFilterCount == -1 && + UnmarshalException.class.equals(rex.getCause().getClass()) && + InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { + return; // normal expected exception + } + rex.printStackTrace(); + Assert.fail("unexpected remote exception", rex); + } catch (Exception rex) { + Assert.fail("unexpected exception", rex); + } + } + + /** + * A simple Serializable holding an object that is passed by value. + * It and its contents are checked by the filter. + */ + static class XX implements Serializable { + private static final long serialVersionUID = 362498820763181265L; + + final Object obj; + + XX(Object obj) { + this.obj = obj; + } + + public String toString() { + return super.toString() + "//" + Objects.toString(obj); + } + } + + interface Echo extends Remote { + int filterCount(Object obj) throws RemoteException; + } + + /** + * This remote object just counts the calls to the serialFilter + * and returns it. The caller can check the number against + * what was expected for the object passed as an argument. + * A new RemoteImpl is used for each test so the count starts at zero again. + */ + static class RemoteImpl implements Echo { + + private static final long serialVersionUID = -6999613679881262446L; + + transient Checker checker; + + static RemoteImpl create() throws RemoteException { + RemoteImpl impl = new RemoteImpl(new Checker()); + return impl; + } + + private RemoteImpl(Checker checker) throws RemoteException { + this.checker = checker; + } + + public int filterCount(Object obj) throws RemoteException { + return checker.count(); + } + + } + + /** + * A ObjectInputFilter that just counts when it is called. + */ + static class Checker implements ObjectInputFilter { + int count; + + @Override + public Status checkInput(FilterInfo filterInfo) { + if (filterInfo.serialClass() == RejectME.class) { + return Status.REJECTED; + } + count++; + return Status.UNDECIDED; + } + + public int count() { + return count; + } + } + + /** + * A class to be rejected by the filter. + */ + static class RejectME implements Serializable { + private static final long serialVersionUID = 2L; + } +} diff --git a/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java b/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java index fe18a8943a5..b96c26499c3 100644 --- a/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java +++ b/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java @@ -40,7 +40,7 @@ import java.util.Base64; /* * @test - * @bug 8048621 8133090 + * @bug 8048621 8133090 8167371 * @summary Test basic operations with keystores (jks, jceks, pkcs12) * @author Yu-Ching Valerie PENG */ @@ -116,6 +116,8 @@ public class TestKeyStoreBasic { }; private static final String ALIAS_HEAD = "test"; + private static final String CRYPTO_ALG = "PBEWithHmacSHA256AndAES_128"; + public static void main(String args[]) throws Exception { TestKeyStoreBasic jstest = new TestKeyStoreBasic(); jstest.run(); @@ -125,7 +127,7 @@ public class TestKeyStoreBasic { for (String provider : PROVIDERS) { try { runTest(provider); - System.out.println("Test with provider " + provider + "passed"); + System.out.println("Test with provider " + provider + " passed"); } catch (java.security.KeyStoreException e) { if (provider.equals("SunPKCS11-Solaris")) { System.out.println("KeyStoreException is expected: " @@ -236,6 +238,44 @@ public class TestKeyStoreBasic { // compare the creation date of the 2 key stores for all aliases compareCreationDate(ks, ks2, numEntries); + // check setEntry/getEntry with a password protection algorithm + if ("PKCS12".equalsIgnoreCase(ks.getType())) { + System.out.println( + "Skipping the setEntry/getEntry check for PKCS12 keystore..."); + return; + } + String alias = ALIAS_HEAD + ALIAS_HEAD; + KeyStore.PasswordProtection pw = + new KeyStore.PasswordProtection(PASSWD2, CRYPTO_ALG, null); + KeyStore.PrivateKeyEntry entry = + new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{ cert }); + checkSetEntry(ks, alias, pw, entry); + ks.setEntry(alias, entry, new KeyStore.PasswordProtection(PASSWD2)); + checkGetEntry(ks, alias, pw); + } + + // check setEntry with a password protection algorithm + private void checkSetEntry(KeyStore ks, String alias, + KeyStore.PasswordProtection pw, KeyStore.Entry entry) throws Exception { + try { + ks.setEntry(alias, entry, pw); + throw new Exception( + "ERROR: expected KeyStore.setEntry to throw an exception"); + } catch (KeyStoreException e) { + // ignore the expected exception + } + } + + // check getEntry with a password protection algorithm + private void checkGetEntry(KeyStore ks, String alias, + KeyStore.PasswordProtection pw) throws Exception { + try { + ks.getEntry(alias, pw); + throw new Exception( + "ERROR: expected KeyStore.getEntry to throw an exception"); + } catch (KeyStoreException e) { + // ignore the expected exception + } } // check key store type diff --git a/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java index ff64add432b..0a596e9d129 100644 --- a/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java +++ b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -624,7 +624,7 @@ public class TestUmmAlQuraChronology { @Test public void test_chronoFields() { ChronoLocalDate hdate = HijrahChronology.INSTANCE.date(1434, 6, 28); - assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), 3); + assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), 7); assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR), 7); assertEquals(hdate.get(ChronoField.ALIGNED_WEEK_OF_MONTH), 4); assertEquals(hdate.get(ChronoField.ALIGNED_WEEK_OF_YEAR), 25); @@ -785,4 +785,32 @@ public class TestUmmAlQuraChronology { public void test_hijrahToJapanese(HijrahDate hijrah, String japanese) { assertEquals(JapaneseChronology.INSTANCE.date(hijrah).toString(), japanese); } + + @DataProvider(name="alignedDayOfWeekInMonthTestDates") + Object[][] data_alignedDayOfWeekInMonth() { + return new Object[][] { + {1437, 9, 1, 1, 1}, + {1437, 10, 1, 1, 1}, + {1437, 10, 11, 2, 4}, + {1437, 10, 29, 5, 1}, + }; + } + + //----------------------------------------------------------------------- + // Test for aligned-week-of-month calculation based on the day-of-month + //----------------------------------------------------------------------- + @Test(dataProvider="alignedDayOfWeekInMonthTestDates") + public void test_alignedWeekOfMonth(int year, int month, int dom, int wom, int dowm) { + HijrahDate date = HijrahChronology.INSTANCE.date(year, month, dom); + assertEquals(date.getLong(ChronoField.ALIGNED_WEEK_OF_MONTH), wom); + } + + //----------------------------------------------------------------------- + // Test for aligned-day-of-week calculation based on the day-of-month + //----------------------------------------------------------------------- + @Test(dataProvider="alignedDayOfWeekInMonthTestDates") + public void test_alignedDayOfWeekInMonth(int year, int month, int dom, int wom, int dowm) { + HijrahDate date = HijrahChronology.INSTANCE.date(year, month, dom); + assertEquals(date.getLong(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), dowm); + } } diff --git a/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java b/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java new file mode 100644 index 00000000000..925e7ec5ef8 --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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.java.time.format; + +/* + * @test + * @bug 8146750 + * @summary Test Narrow and NarrowStandalone month names are retrieved correctly. + */ +import static org.testng.Assert.assertEquals; + +import java.time.DayOfWeek; +import java.time.Month; +import java.time.format.TextStyle; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class TestNarrowMonthNamesAndDayNames { + + static { + System.setProperty("java.locale.providers", "COMPAT"); + } + + private static final List MONTHVALUES = Arrays.asList(Month.values()); + private static final List DAYVALUES = Arrays.asList(DayOfWeek.values()); + private static final List TEXTSTYLELIST = Arrays.asList(TextStyle.NARROW, + TextStyle.NARROW_STANDALONE); + private static final List LOCARR = Arrays.asList(Locale.US, + Locale.GERMANY, + Locale.FRANCE, + new Locale("no", "NO")); + + /** + * Locale en_US, de_DE, fr_FR, no_NO will have same Narrow and + * Narrow_Standalone month Names for COMPAT Provider. + */ + @DataProvider(name = "MonthNarrows") + public Object[][] monthNameData() { + return new Object[][]{{new String[]{ + "J", + "F", + "M", + "A", + "M", + "J", + "J", + "A", + "S", + "O", + "N", + "D" + }},}; + } + + //----------------------------------------------------------------------- + // Check Narrow and Narrow_standalone month name values + //----------------------------------------------------------------------- + @Test(dataProvider = "MonthNarrows") + public void compareMonthNarrowValues(String[] monthNarrowExpected) { + LOCARR.forEach((loc) -> { + TEXTSTYLELIST.forEach((style) -> { + MONTHVALUES.forEach((value) -> { + String result = value.getDisplayName(style, loc); + int index = value.ordinal(); + assertEquals(result, monthNarrowExpected[index], "Test failed" + + " for COMPAT Provider for locale " + + loc + " for style " + style.name() + + " with Month value " + value.name()); + }); + }); + }); + } + + /** + * Locale en_US, de_DE, fr_FR, no_NO will have different Narrow and + * Narrow_Standalone Day Names for COMPAT Provider. + */ + @DataProvider(name = "DayNarrows") + public Object[][] dayNameData() { + return new Object[][]{ + {Locale.US, new String[]{"M", "T", "W", "T", "F", "S", "S"}}, + {Locale.GERMANY, new String[]{"M", "D", "M", "D", "F", "S", "S"}}, + {Locale.FRANCE, new String[]{"L", "M", "M", "J", "V", "S", "D"}}, + {new Locale("no", "NO"), new String[]{"M", "T", "O", "T", "F", "L", "S"}},}; + } + + //----------------------------------------------------------------------- + // Check Narrow and Narrow_standalone Day name values + //----------------------------------------------------------------------- + @Test(dataProvider = "DayNarrows") + public void compareDayNarrowValues(Locale locale, String[] dayNarrowExpected) { + TEXTSTYLELIST.forEach((style) -> { + DAYVALUES.forEach((value) -> { + String result = value.getDisplayName(style, locale); + int index = value.ordinal(); + assertEquals(result, dayNarrowExpected[index], "Test failed" + + " for COMPAT Provider for locale " + + locale + " for style " + style.name() + + " with Day value " + value.name()); + }); + }); + } +} diff --git a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh index 6beb911b124..b39efb0bd71 100644 --- a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh +++ b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh @@ -88,6 +88,7 @@ fi ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ + -Djava.security.properties=${TESTSRC}${FS}security.properties \ -classpath "${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}." \ FailOverTest result=$? diff --git a/jdk/test/javax/crypto/SecretKeyFactory/security.properties b/jdk/test/javax/crypto/SecretKeyFactory/security.properties new file mode 100644 index 00000000000..f855f12b990 --- /dev/null +++ b/jdk/test/javax/crypto/SecretKeyFactory/security.properties @@ -0,0 +1,6 @@ +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + +jdk.security.provider.preferred= +jdk.jar.disabledAlgorithms= + diff --git a/jdk/test/javax/net/ssl/templates/SSLTest.java b/jdk/test/javax/net/ssl/templates/SSLTest.java index 48196fda86e..61ab7ae0a15 100644 --- a/jdk/test/javax/net/ssl/templates/SSLTest.java +++ b/jdk/test/javax/net/ssl/templates/SSLTest.java @@ -94,12 +94,22 @@ public class SSLTest { /* * Is the server ready to serve? */ - private final CountDownLatch serverCondition = new CountDownLatch(1); + private final CountDownLatch serverReadyCondition = new CountDownLatch(1); /* * Is the client ready to handshake? */ - private final CountDownLatch clientCondition = new CountDownLatch(1); + private final CountDownLatch clientReadyCondition = new CountDownLatch(1); + + /* + * Is the server done? + */ + private final CountDownLatch serverDoneCondition = new CountDownLatch(1); + + /* + * Is the client done? + */ + private final CountDownLatch clientDoneCondition = new CountDownLatch(1); /* * Public API. @@ -162,6 +172,25 @@ public class SSLTest { return keystore; } + // Try to accept a connection in 30 seconds. + public static SSLSocket accept(SSLServerSocket sslServerSocket) + throws IOException { + + return accept(sslServerSocket, SERVER_TIMEOUT); + } + + public static SSLSocket accept(SSLServerSocket sslServerSocket, int timeout) + throws IOException { + + try { + sslServerSocket.setSoTimeout(timeout); + return (SSLSocket) sslServerSocket.accept(); + } catch (SocketTimeoutException ste) { + sslServerSocket.close(); + return null; + } + } + public SSLTest setSeparateServerThread(boolean separateServerThread) { this.separateServerThread = separateServerThread; return this; @@ -202,33 +231,61 @@ public class SSLTest { } public void signalServerReady() { - serverCondition.countDown(); + serverReadyCondition.countDown(); + } + + public void signalServerDone() { + serverDoneCondition.countDown(); } public boolean waitForClientSignal(long timeout, TimeUnit unit) throws InterruptedException { - return clientCondition.await(timeout, unit); + return clientReadyCondition.await(timeout, unit); } public boolean waitForClientSignal() throws InterruptedException { return waitForClientSignal(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); } + public boolean waitForClientDone(long timeout, TimeUnit unit) + throws InterruptedException { + + return clientDoneCondition.await(timeout, unit); + } + + public boolean waitForClientDone() throws InterruptedException { + return waitForClientDone(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); + } + public void signalClientReady() { - clientCondition.countDown(); + clientReadyCondition.countDown(); + } + + public void signalClientDone() { + clientDoneCondition.countDown(); } public boolean waitForServerSignal(long timeout, TimeUnit unit) throws InterruptedException { - return serverCondition.await(timeout, unit); + return serverReadyCondition.await(timeout, unit); } public boolean waitForServerSignal() throws InterruptedException { return waitForServerSignal(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); } + public boolean waitForServerDone(long timeout, TimeUnit unit) + throws InterruptedException { + + return serverDoneCondition.await(timeout, unit); + } + + public boolean waitForServerDone() throws InterruptedException { + return waitForServerDone(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); + } + public SSLTest setServerPeer(Peer serverPeer) { this.serverPeer = serverPeer; return this; @@ -310,19 +367,14 @@ public class SSLTest { test.signalServerReady(); // Try to accept a connection in 30 seconds. - SSLSocket sslSocket; - try { - sslServerSocket.setSoTimeout(SERVER_TIMEOUT); - sslSocket = (SSLSocket) sslServerSocket.accept(); - print("Server accepted connection"); - } catch (SocketTimeoutException ste) { - sslServerSocket.close(); - + SSLSocket sslSocket = accept(sslServerSocket); + if (sslSocket == null) { // Ignore the test case if no connection within 30 seconds. print("No incoming client connection in 30 seconds. " - + "Ignore in server side.", ste); + + "Ignore in server side."); return; } + print("Server accepted connection"); // handle the connection try { @@ -353,6 +405,8 @@ public class SSLTest { sslSocket.close(); sslServerSocket.close(); } + + test.signalServerDone(); } /* @@ -419,6 +473,8 @@ public class SSLTest { print("Run client application"); test.getClientApplication().run(sslSocket, test); } + + test.signalClientDone(); } /* diff --git a/jdk/test/javax/script/DummyScriptEngineFactory.java b/jdk/test/javax/script/DummyScriptEngineFactory.java index 1b90d1a959d..af842993a5d 100644 --- a/jdk/test/javax/script/DummyScriptEngineFactory.java +++ b/jdk/test/javax/script/DummyScriptEngineFactory.java @@ -91,9 +91,10 @@ public class DummyScriptEngineFactory implements ScriptEngineFactory { } public String getProgram(String... statements) { + Objects.requireNonNull(statements); StringBuffer buf = new StringBuffer(); - for (int i = 0; i < statements.length; i++) { - buf.append(statements[i]); + for (String stat : statements) { + buf.append(Objects.requireNonNull(stat)); } return buf.toString(); } diff --git a/jdk/test/jdk/internal/util/jar/TestVersionedStream.java b/jdk/test/jdk/internal/util/jar/TestVersionedStream.java index 12e45f03b77..5dbef938752 100644 --- a/jdk/test/jdk/internal/util/jar/TestVersionedStream.java +++ b/jdk/test/jdk/internal/util/jar/TestVersionedStream.java @@ -25,13 +25,14 @@ * @test * @bug 8163798 * @summary basic tests for multi-release jar versioned streams + * @library /lib/testlibrary * @modules jdk.jartool/sun.tools.jar java.base/jdk.internal.util.jar + * @build jdk.testlibrary.FileUtils * @run testng TestVersionedStream */ import org.testng.Assert; import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -40,29 +41,31 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import java.net.URI; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.ZipFile; -public class TestVersionedStream { - private String userdir; +import jdk.testlibrary.FileUtils; - @BeforeClass - public void initialize() { - userdir = System.getProperty("user.dir", "."); +public class TestVersionedStream { + private final Path userdir; + private final Set unversionedEntryNames; + + public TestVersionedStream() throws IOException { + userdir = Paths.get(System.getProperty("user.dir", ".")); // These are not real class files even though they end with .class. // They are resource files so jar tool validation won't reject them. @@ -70,91 +73,103 @@ public class TestVersionedStream { // could be in a concealed package if this was a modular multi-release // jar. createFiles( + "base/p/Bar.class", "base/p/Foo.class", "base/p/Main.class", "v9/p/Foo.class", "v10/p/Foo.class", "v10/q/Bar.class", + "v11/p/Bar.class", "v11/p/Foo.class" ); - jar("cf mmr.jar -C base . --release 9 -C v9 . --release 10 -C v10 . --release 11 -C v11 ."); + jar("cf mmr.jar -C base . --release 9 -C v9 . " + + "--release 10 -C v10 . --release 11 -C v11 ."); System.out.println("Contents of mmr.jar\n======="); - jar("tf mmr.jar"); + + try(JarFile jf = new JarFile("mmr.jar")) { + unversionedEntryNames = jf.stream() + .map(je -> je.getName()) + .peek(System.out::println) + .map(nm -> nm.startsWith("META-INF/versions/") + ? nm.replaceFirst("META-INF/versions/\\d+/", "") + : nm) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + System.out.println("======="); } @AfterClass public void close() throws IOException { - Path root = Paths.get(userdir); - Files.walkFileTree(root, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - if (!dir.equals(root)) { - Files.delete(dir); - } - return FileVisitResult.CONTINUE; - } - }); + Files.walk(userdir, 1) + .filter(p -> !p.equals(userdir)) + .forEach(p -> { + try { + if (Files.isDirectory(p)) { + FileUtils.deleteFileTreeWithRetry(p); + } else { + FileUtils.deleteFileIfExistsWithRetry(p); + } + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); } @DataProvider public Object[][] data() { - List p = List.of( - "META-INF/", - "META-INF/MANIFEST.MF", - "p/", - "p/Foo.class", - "p/Main.class" - ); - List q = List.of( - "META-INF/", - "META-INF/MANIFEST.MF", - "p/", - "p/Foo.class", - "p/Main.class", - "q/", - "q/Bar.class" - ); - Runtime.Version rt = JarFile.runtimeVersion(); return new Object[][] { - {Runtime.Version.parse("8"), p}, - {Runtime.Version.parse("9"), p}, - {Runtime.Version.parse("10"), q}, - {Runtime.Version.parse("11"), q}, - {JarFile.baseVersion(), p}, - {rt, rt.major() > 9 ? q : p} + {Runtime.Version.parse("8")}, + {Runtime.Version.parse("9")}, + {Runtime.Version.parse("10")}, + {Runtime.Version.parse("11")}, + {JarFile.baseVersion()}, + {JarFile.runtimeVersion()} }; } @Test(dataProvider="data") - public void test(Runtime.Version version, List names) throws Exception { + public void test(Runtime.Version version) throws Exception { try (JarFile jf = new JarFile(new File("mmr.jar"), false, ZipFile.OPEN_READ, version); - Stream jes = jdk.internal.util.jar.VersionedStream.stream(jf)) + Stream jes = jdk.internal.util.jar.VersionedStream.stream(jf)) { Assert.assertNotNull(jes); - List entries = jes.collect(Collectors.toList()); + // put versioned entries in list so we can reuse them + List versionedEntries = jes.collect(Collectors.toList()); - // verify the correct order - List enames = entries.stream() - .map(je -> je.getName()) - .collect(Collectors.toList()); - Assert.assertEquals(enames, names); + Assert.assertTrue(versionedEntries.size() > 0); + + // also keep the names + List versionedNames = new ArrayList<>(versionedEntries.size()); + + // verify the correct order while building enames + Iterator allIt = unversionedEntryNames.iterator(); + Iterator verIt = versionedEntries.iterator(); + boolean match = false; + + while (verIt.hasNext()) { + match = false; + if (!allIt.hasNext()) break; + String name = verIt.next().getName(); + versionedNames.add(name); + while (allIt.hasNext()) { + if (name.equals(allIt.next())) { + match = true; + break; + } + } + } + if (!match) { + Assert.fail("versioned entries not in same order as unversioned entries"); + } // verify the contents Map contents = new HashMap<>(); + contents.put("p/Bar.class", "base/p/Bar.class\n"); contents.put("p/Main.class", "base/p/Main.class\n"); - if (version.major() > 9) { - contents.put("q/Bar.class", "v10/q/Bar.class\n"); - } switch (version.major()) { case 8: contents.put("p/Foo.class", "base/p/Foo.class\n"); @@ -164,9 +179,12 @@ public class TestVersionedStream { break; case 10: contents.put("p/Foo.class", "v10/p/Foo.class\n"); + contents.put("q/Bar.class", "v10/q/Bar.class\n"); break; case 11: + contents.put("p/Bar.class", "v11/p/Bar.class\n"); contents.put("p/Foo.class", "v11/p/Foo.class\n"); + contents.put("q/Bar.class", "v10/q/Bar.class\n"); break; default: Assert.fail("Test out of date, please add more cases"); @@ -174,9 +192,9 @@ public class TestVersionedStream { contents.entrySet().stream().forEach(e -> { String name = e.getKey(); - int i = enames.indexOf(name); + int i = versionedNames.indexOf(name); Assert.assertTrue(i != -1, name + " not in enames"); - JarEntry je = entries.get(i); + JarEntry je = versionedEntries.get(i); try (InputStream is = jf.getInputStream(je)) { String s = new String(is.readAllBytes()); Assert.assertTrue(s.endsWith(e.getValue()), s); @@ -210,5 +228,4 @@ public class TestVersionedStream { new sun.tools.jar.Main(System.out, System.err, "jar") .run(args.split(" +")); } - } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java index fab9b8a930e..07fd00c19e6 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java @@ -24,6 +24,7 @@ package jdk.testlibrary; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -40,7 +41,8 @@ import java.util.jar.Manifest; public final class JarUtils { /** - * Create jar file with specified files. + * Create jar file with specified files. If a specified file does not exist, + * a new jar entry will be created with the file name itself as the content. */ public static void createJar(String dest, String... files) throws IOException { @@ -54,6 +56,8 @@ public final class JarUtils { jos.putNextEntry(new JarEntry(file)); try (FileInputStream fis = new FileInputStream(file)) { fis.transferTo(jos); + } catch (FileNotFoundException e) { + jos.write(file.getBytes()); } } } @@ -61,7 +65,17 @@ public final class JarUtils { } /** - * Add specified files to existing jar file. + * Add or remove specified files to existing jar file. If a specified file + * to be updated or added does not exist, the jar entry will be created + * with the file name itself as the content. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param files the files to update. The list is broken into 2 groups + * by a "-" string. The files before in the 1st group will + * be either updated or added. The files in the 2nd group + * will be removed. If no "-" exists, all files belong to + * the 1st group. */ public static void updateJar(String src, String dest, String... files) throws IOException { @@ -77,8 +91,11 @@ public final class JarUtils { JarEntry entry = entries.nextElement(); String name = entry.getName(); boolean found = false; + boolean update = true; for (String file : files) { - if (name.equals(file)) { + if (file.equals("-")) { + update = false; + } else if (name.equals(file)) { updatedFiles.add(file); found = true; break; @@ -86,11 +103,18 @@ public final class JarUtils { } if (found) { - System.out.println(String.format("Updating %s with %s", - dest, name)); - jos.putNextEntry(new JarEntry(name)); - try (FileInputStream fis = new FileInputStream(name)) { - fis.transferTo(jos); + if (update) { + System.out.println(String.format("Updating %s with %s", + dest, name)); + jos.putNextEntry(new JarEntry(name)); + try (FileInputStream fis = new FileInputStream(name)) { + fis.transferTo(jos); + } catch (FileNotFoundException e) { + jos.write(name.getBytes()); + } + } else { + System.out.println(String.format("Removing %s from %s", + name, dest)); } } else { System.out.println(String.format("Copying %s to %s", @@ -103,12 +127,17 @@ public final class JarUtils { // append new files for (String file : files) { + if (file.equals("-")) { + break; + } if (!updatedFiles.contains(file)) { System.out.println(String.format("Adding %s with %s", dest, file)); jos.putNextEntry(new JarEntry(file)); try (FileInputStream fis = new FileInputStream(file)) { fis.transferTo(jos); + } catch (FileNotFoundException e) { + jos.write(file.getBytes()); } } } diff --git a/jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java deleted file mode 100644 index b24aed6fd73..00000000000 --- a/jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * - * This is a HTTP test server used by the regression test - * for the bug fixes: 4323990, 4413069 - */ - -import java.io.*; -import java.net.*; -import javax.net.*; - -/* - * OriginServer.java -- a simple server that can serve - * Http get request in both clear and secure channel - */ - -public abstract class OriginServer implements Runnable { - - private ServerSocket server = null; - Exception serverException = null; - /** - * Constructs a OriginServer based on ss and - * obtains a response data's bytecodes using the method - * getBytes. - */ - protected OriginServer(ServerSocket ss) throws Exception - { - server = ss; - newListener(); - if (serverException != null) - throw serverException; - } - - /** - * Returns an array of bytes containing the bytes for - * the data sent in the response. - * - * @return the bytes for the information that is being sent - */ - public abstract byte[] getBytes(); - - /** - * The "listen" thread that accepts a connection to the - * server, parses the header and sends back the response - */ - public void run() - { - Socket socket; - - // accept a connection - try { - socket = server.accept(); - } catch (IOException e) { - System.out.println("Class Server died: " + e.getMessage()); - serverException = e; - return; - } - try { - DataOutputStream out = - new DataOutputStream(socket.getOutputStream()); - try { - BufferedReader in = - new BufferedReader(new InputStreamReader( - socket.getInputStream())); - // read the request - readRequest(in); - // retrieve bytecodes - byte[] bytecodes = getBytes(); - // send bytecodes in response (assumes HTTP/1.0 or later) - try { - out.writeBytes("HTTP/1.0 200 OK\r\n"); - out.writeBytes("Content-Length: " + bytecodes.length + - "\r\n"); - out.writeBytes("Content-Type: text/html\r\n\r\n"); - out.write(bytecodes); - out.flush(); - } catch (IOException ie) { - serverException = ie; - return; - } - - } catch (Exception e) { - // write out error response - out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n"); - out.writeBytes("Content-Type: text/html\r\n\r\n"); - out.flush(); - } - - } catch (IOException ex) { - System.out.println("error writing response: " + ex.getMessage()); - serverException = ex; - - } finally { - try { - socket.close(); - } catch (IOException e) { - serverException = e; - } - } - } - - /** - * Create a new thread to listen. - */ - private void newListener() - { - (new Thread(this)).start(); - } - - /** - * read the response, don't care for the syntax of the request-line - * for this testing - */ - private static void readRequest(BufferedReader in) - throws IOException - { - String line = null; - System.out.println("Server received: "); - do { - if (line != null) - System.out.println(line); - line = in.readLine(); - } while ((line.length() != 0) && - (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); - } -} diff --git a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java index 2eef7f42e8b..4e4b8379bad 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * 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,22 +23,38 @@ /* * @test - * @bug 4323990 4413069 + * @bug 4323990 4413069 8160838 * @summary HttpsURLConnection doesn't send Proxy-Authorization on CONNECT * Incorrect checking of proxy server response * @modules java.base/sun.net.www - * @run main/othervm ProxyAuthTest - * - * No way to reserve and restore java.lang.Authenticator, need to run this - * test in othervm mode. + * @library /javax/net/ssl/templates + * @run main/othervm ProxyAuthTest fail + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic ProxyAuthTest fail + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic, ProxyAuthTest fail + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=BAsIc ProxyAuthTest fail + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic,Digest ProxyAuthTest fail + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Unknown,bAsIc ProxyAuthTest fail + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes= ProxyAuthTest succeed + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Digest,NTLM,Negotiate ProxyAuthTest succeed + * @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=UNKNOWN,notKnown ProxyAuthTest succeed */ -import java.io.*; -import java.net.*; -import java.security.KeyStore; -import javax.net.*; -import javax.net.ssl.*; -import java.security.cert.*; +// No way to reserve and restore java.lang.Authenticator, as well as read-once +// system properties, so this tests needs to run in othervm mode. + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.URL; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +import static java.nio.charset.StandardCharsets.US_ASCII; /* * ProxyAuthTest.java -- includes a simple server that can serve @@ -56,132 +72,167 @@ public class ProxyAuthTest { static String trustStoreFile = "truststore"; static String passwd = "passphrase"; - volatile private static int serverPort = 0; - - /* - * The TestServer implements a OriginServer that - * processes HTTP requests and responses. + /** + * read the response, don't care for the syntax of the request-line + * for this testing */ - static class TestServer extends OriginServer { - public TestServer(ServerSocket ss) throws Exception { - super(ss); - } - - /* - * Returns an array of bytes containing the bytes for - * the data sent in the response. - * - * @return bytes for the data in the response - */ - public byte[] getBytes() { - return "Proxy authentication for tunneling succeeded ..". - getBytes(); - } + private static void readRequest(BufferedReader in) throws IOException { + String line = null; + System.out.println("Server received: "); + do { + if (line != null) { + System.out.println(line); + } + line = in.readLine(); + } while ((line.length() != 0) && + (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); } /* * Main method to create the server and the client */ public static void main(String args[]) throws Exception { + boolean expectSuccess; + expectSuccess = args[0].equals("succeed"); + String keyFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + keyStoreFile; + SSLTest.TEST_SRC + "/" + pathToStores + "/" + keyStoreFile; String trustFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + trustStoreFile; + SSLTest.TEST_SRC + "/" + pathToStores + "/" + trustStoreFile; - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", passwd); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", passwd); + SSLTest.setup(keyFilename, trustFilename, passwd); - boolean useSSL = true; - /* - * setup the server - */ - try { - ServerSocketFactory ssf = - ProxyAuthTest.getServerSocketFactory(useSSL); - ServerSocket ss = ssf.createServerSocket(serverPort); - serverPort = ss.getLocalPort(); - new TestServer(ss); - } catch (Exception e) { - System.out.println("Server side failed:" + - e.getMessage()); - throw e; - } - // trigger the client - try { - doClientSide(); - } catch (Exception e) { - System.out.println("Client side failed: " + e.getMessage()); - throw e; - } + new SSLTest() + .setServerApplication((socket, test) -> { + DataOutputStream out = new DataOutputStream( + socket.getOutputStream()); + + try { + BufferedReader in = new BufferedReader( + new InputStreamReader(socket.getInputStream())); + + // read the request + readRequest(in); + + // retrieve bytecodes + byte[] bytecodes = + "Proxy authentication for tunneling succeeded .." + .getBytes(US_ASCII); + + // send bytecodes in response (assumes HTTP/1.0 or later) + out.writeBytes("HTTP/1.0 200 OK\r\n"); + out.writeBytes("Content-Length: " + bytecodes.length + + "\r\n"); + out.writeBytes("Content-Type: text/html\r\n\r\n"); + out.write(bytecodes); + out.flush(); + } catch (IOException e) { + // write out error response + out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n"); + out.writeBytes("Content-Type: text/html\r\n\r\n"); + out.flush(); + } + }) + .setClientPeer(test -> { + try { + doClientSide(test); + if (!expectSuccess) { + throw new RuntimeException("Expected exception/failure " + + "to connect, but succeeded."); + } + } catch (IOException e) { + if (expectSuccess) { + System.out.println("Client side failed: " + + e.getMessage()); + throw e; + } + + if (! (e.getMessage().contains( + "Unable to tunnel through proxy") && + e.getMessage().contains("407")) ) { + + throw new RuntimeException( + "Expected exception about cannot tunnel, " + + "407, etc, but got", e); + } else { + // Informative + System.out.println("Caught expected exception: " + + e.getMessage()); + } + } + }) + .runTest(); } - private static ServerSocketFactory getServerSocketFactory - (boolean useSSL) throws Exception { - if (useSSL) { - SSLServerSocketFactory ssf = null; - // set up key manager to do server authentication - SSLContext ctx; - KeyManagerFactory kmf; - KeyStore ks; - char[] passphrase = passwd.toCharArray(); + static void doClientSide(SSLTest test) throws IOException { - ctx = SSLContext.getInstance("TLS"); - kmf = KeyManagerFactory.getInstance("SunX509"); - ks = KeyStore.getInstance("JKS"); - - ks.load(new FileInputStream(System.getProperty( - "javax.net.ssl.keyStore")), passphrase); - kmf.init(ks, passphrase); - ctx.init(kmf.getKeyManagers(), null, null); - - ssf = ctx.getServerSocketFactory(); - return ssf; - } else { - return ServerSocketFactory.getDefault(); + // Wait for server to get started. + // + // The server side takes care of the issue if the server cannot + // get started in 90 seconds. The client side would just ignore + // the test case if the serer is not ready. + try { + if (!test.waitForServerSignal()) { + System.out.print("The server is not ready yet in 90 seconds. " + + "Ignore in client side."); + return; + } + } catch (InterruptedException e) { + System.out.print("InterruptedException occured. " + + "Ignore in client side."); + return; } - } - static void doClientSide() throws Exception { /* * setup up a proxy with authentication information */ - setupProxy(); + ProxyTunnelServer ps = setupProxy(); /* * we want to avoid URLspoofCheck failures in cases where the cert * DN name does not match the hostname in the URL. */ - HttpsURLConnection.setDefaultHostnameVerifier( - new NameVerifier()); - URL url = new URL("https://" + "localhost:" + serverPort - + "/index.html"); - BufferedReader in = null; - try { - in = new BufferedReader(new InputStreamReader( - url.openStream())); + HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); + + InetSocketAddress paddr = new InetSocketAddress( + "localhost", ps.getPort()); + Proxy proxy = new Proxy(Proxy.Type.HTTP, paddr); + + URL url = new URL("https://" + "localhost:" + test.getServerPort() + + "/index.html"); + + // Signal the server, the client is ready to communicate. + test.signalClientReady(); + + HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(proxy); + try (BufferedReader in = new BufferedReader( + new InputStreamReader(uc.getInputStream()))) { + String inputLine; System.out.print("Client recieved from the server: "); - while ((inputLine = in.readLine()) != null) + while ((inputLine = in.readLine()) != null) { System.out.println(inputLine); - in.close(); - } catch (SSLException e) { - if (in != null) - in.close(); + } + } catch (IOException e) { + // Assert that the error stream is not accessible from the failed + // tunnel setup. + if (uc.getErrorStream() != null) { + throw new RuntimeException("Unexpected error stream."); + } + throw e; } } static class NameVerifier implements HostnameVerifier { + + @Override public boolean verify(String hostname, SSLSession session) { return true; } } - static void setupProxy() throws IOException { + static ProxyTunnelServer setupProxy() throws IOException { ProxyTunnelServer pserver = new ProxyTunnelServer(); /* * register a system wide authenticator and setup the proxy for @@ -194,16 +245,14 @@ public class ProxyAuthTest { pserver.setUserAuth("Test", "test123"); pserver.start(); - System.setProperty("https.proxyHost", "localhost"); - System.setProperty("https.proxyPort", String.valueOf( - pserver.getPort())); + return pserver; } public static class TestAuthenticator extends Authenticator { + @Override public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication("Test", - "test123".toCharArray()); + return new PasswordAuthentication("Test", "test123".toCharArray()); } } } diff --git a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyTunnelServer.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyTunnelServer.java index 145cb49c541..90315e8cc84 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyTunnelServer.java +++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyTunnelServer.java @@ -65,6 +65,7 @@ public class ProxyTunnelServer extends Thread { ss = (ServerSocket) ServerSocketFactory.getDefault(). createServerSocket(0); } + setDaemon(true); } public void needUserAuth(boolean auth) { @@ -211,6 +212,7 @@ public class ProxyTunnelServer extends Thread { this.sockOut = sockOut; input = sockIn.getInputStream(); output = sockOut.getOutputStream(); + setDaemon(true); } public void run() { diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh index 1726d7092f0..8015e7b944b 100644 --- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh @@ -57,5 +57,6 @@ ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} ${TESTSRC}${FS}ProxyTunnelServer.java \ ${TESTSRC}${FS}PostThruProxyWithAuth.java ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} \ + -Djdk.http.auth.tunneling.disabledSchemes= \ PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC} exit diff --git a/jdk/test/sun/net/www/protocol/jar/B4957695.java b/jdk/test/sun/net/www/protocol/jar/B4957695.java index 3ab0f0c7562..6f9089d4971 100644 --- a/jdk/test/sun/net/www/protocol/jar/B4957695.java +++ b/jdk/test/sun/net/www/protocol/jar/B4957695.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /** * @test * @bug 4957695 + * @run main/othervm -Djava.io.tmpdir=. B4957695 * @summary URLJarFile.retrieve does not delete tmpFile on IOException */ diff --git a/jdk/test/sun/nio/cs/TestHKSCS.java b/jdk/test/sun/nio/cs/TestHKSCS.java new file mode 100644 index 00000000000..0a7f4559d32 --- /dev/null +++ b/jdk/test/sun/nio/cs/TestHKSCS.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8166258 + * @summary Some corner cases for hkscs charsets + * @modules jdk.charsets + * @run main TestHKSCS + */ + +import java.util.Arrays; + +public class TestHKSCS { + public static void main(String args[]) throws Exception { + String[] charsets = { "x-MS950-HKSCS-XP", + "x-MS950-HKSCS", + "Big5-HKSCS", + "x-Big5-HKSCS-2001" + }; + String s = "\ufffd\ud87f\udffd"; + byte[] bytes = new byte[] { 0x3f, 0x3f }; + for (String cs : charsets) { + if (!Arrays.equals(bytes, s.getBytes(cs))) { + throw new RuntimeException(cs + " failed to decode u+fffd"); + } + } + } +} diff --git a/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java new file mode 100644 index 00000000000..82a5000895c --- /dev/null +++ b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.OptionalDataException; +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import sun.reflect.ReflectionFactory; + +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import org.testng.TestNG; + +/* + * @test + * @bug 8137058 8164908 + * @run testng ReflectionFactoryTest + * @run testng/othervm/policy=security.policy ReflectionFactoryTest + * @summary Basic test for the unsupported ReflectionFactory + * @modules jdk.unsupported + */ + +public class ReflectionFactoryTest { + + // Initialized by init() + static ReflectionFactory factory; + + @DataProvider(name = "ClassConstructors") + static Object[][] classConstructors() { + return new Object[][] { + {Object.class}, + {Foo.class}, + {Bar.class}, + }; + } + + @BeforeClass + static void init() { + factory = ReflectionFactory.getReflectionFactory(); + } + + /** + * Test that the correct Constructor is selected and run. + * @param type type of object to create + * @throws NoSuchMethodException - error + * @throws InstantiationException - error + * @throws IllegalAccessException - error + * @throws InvocationTargetException - error + */ + @Test(dataProvider="ClassConstructors") + static void testConstructor(Class type) + throws NoSuchMethodException, InstantiationException, + IllegalAccessException, InvocationTargetException + { + @SuppressWarnings("unchecked") + Constructor c = factory.newConstructorForSerialization(type); + + Object o = c.newInstance(); + Assert.assertEquals(o.getClass(), type, "Instance is wrong type"); + if (o instanceof Foo) { + Foo foo = (Foo)o; + foo.check(); + } + } + + static class Foo { + private int foo; + public Foo() { + this.foo = 1; + } + + public String toString() { + return "foo: " + foo; + } + + public void check() { + int expectedFoo = 1; + Assert.assertEquals(foo, expectedFoo, "foo() constructor not run"); + } + } + + static class Bar extends Foo implements Serializable { + private int bar; + public Bar() { + this.bar = 1; + } + + public String toString() { + return super.toString() + ", bar: " + bar; + } + + public void check() { + super.check(); + int expectedBar = 0; + Assert.assertEquals(bar, expectedBar, "bar() constructor not run"); + } + } + + /** + * Test newConstructorForExternalization returns the constructor and it can be called. + * @throws NoSuchMethodException - error + * @throws InstantiationException - error + * @throws IllegalAccessException - error + * @throws InvocationTargetException - error + */ + @Test + static void newConstructorForExternalization() + throws NoSuchMethodException, InstantiationException, + IllegalAccessException, InvocationTargetException { + Constructor cons = factory.newConstructorForExternalization(Ext.class); + Ext ext = (Ext)cons.newInstance(); + Assert.assertEquals(ext.ext, 1, "Constructor not run"); + } + + static class Ext implements Externalizable { + private static final long serialVersionUID = 1L; + + int ext; + + public Ext() { + ext = 1; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException {} + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {} + } + + @Test + static void testReadWriteObjectForSerialization() throws Throwable { + MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class); + Assert.assertNotNull(readObjectMethod, "readObjectMethod not found"); + + MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class); + Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found"); + + MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class); + Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found"); + + MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class); + Assert.assertNotNull(readResolveMethod, "readResolveMethod not found"); + + MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class); + Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found"); + + byte[] data = null; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) { + Ser ser = new Ser(); + + writeReplaceMethod.invoke(ser); + Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called"); + Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called"); + + writeObjectMethod.invoke(ser, oos); + Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called"); + Assert.assertTrue(ser.writeObjectCalled, "writeObject not called"); + oos.flush(); + data = baos.toByteArray(); + } + + try (ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInputStream ois = new ObjectInputStream(bais)) { + Ser ser2 = new Ser(); + + readObjectMethod.invoke(ser2, ois); + Assert.assertTrue(ser2.readObjectCalled, "readObject not called"); + Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called"); + Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called"); + + readObjectNoDataMethod.invoke(ser2, ois); + Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called"); + Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called"); + Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called"); + + readResolveMethod.invoke(ser2); + Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called"); + Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called"); + Assert.assertTrue(ser2.readResolveCalled, "readResolve not called"); + } + } + + @Test + static void hasStaticInitializer() { + boolean actual = factory.hasStaticInitializerForSerialization(Ser.class); + Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong"); + } + + static class Ser implements Serializable { + private static final long serialVersionUID = 2L; + static { + // Define a static class initialization method + } + + boolean readObjectCalled = false; + boolean readObjectNoDataCalled = false; + boolean writeObjectCalled = false; + boolean readResolveCalled = false; + boolean writeReplaceCalled = false; + + public Ser() {} + + private void readObject(ObjectInputStream ois) throws IOException { + Assert.assertFalse(writeObjectCalled, "readObject called too many times"); + readObjectCalled = ois.readBoolean(); + } + + private void readObjectNoData(ObjectInputStream ois) throws IOException { + Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times"); + readObjectNoDataCalled = true; + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + Assert.assertFalse(writeObjectCalled, "writeObject called too many times"); + writeObjectCalled = true; + oos.writeBoolean(writeObjectCalled); + } + + private Object writeReplace() { + Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times"); + writeReplaceCalled = true; + return this; + } + + private Object readResolve() { + Assert.assertFalse(readResolveCalled, "readResolve called too many times"); + readResolveCalled = true; + return this; + } + } + + /** + * Test the constructor of OptionalDataExceptions. + */ + @Test + static void newOptionalDataException() { + OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true); + Assert.assertTrue(ode.eof, "eof wrong"); + ode = factory.newOptionalDataExceptionForSerialization(false); + Assert.assertFalse(ode.eof, "eof wrong"); + + } + + + + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + @Test(enabled = false) + public static void main(String[] args) { + Class[] testclass = {ReflectionFactoryTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } +} diff --git a/jdk/test/sun/reflect/ReflectionFactory/security.policy b/jdk/test/sun/reflect/ReflectionFactory/security.policy new file mode 100644 index 00000000000..8c30f3b278c --- /dev/null +++ b/jdk/test/sun/reflect/ReflectionFactory/security.policy @@ -0,0 +1,11 @@ +// Individual Permissions for ReflectionFactoryTest +grant { + // Permissions needed to run the test + permission java.util.PropertyPermission "*", "read"; + permission java.io.FilePermission "<>", "read,write,delete,execute"; + + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect"; + permission java.lang.RuntimePermission "reflectionFactoryAccess"; +}; diff --git a/jdk/test/sun/security/ec/TestEC.java b/jdk/test/sun/security/ec/TestEC.java index 4b055706b19..de3783da260 100644 --- a/jdk/test/sun/security/ec/TestEC.java +++ b/jdk/test/sun/security/ec/TestEC.java @@ -28,7 +28,7 @@ /** * @test - * @bug 6840752 + * @bug 6840752 8168078 * @summary Provide out-of-the-box support for ECC algorithms * @library ../pkcs11 * @library ../pkcs11/ec @@ -37,6 +37,7 @@ * @modules jdk.crypto.pkcs11/sun.security.pkcs11.wrapper * @compile -XDignore.symbol.file TestEC.java * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC + * @run main/othervm/java.security.policy=TestEC.policy -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC */ import java.security.NoSuchProviderException; diff --git a/jdk/test/sun/security/ec/TestEC.policy b/jdk/test/sun/security/ec/TestEC.policy new file mode 100644 index 00000000000..de20d3b7bd1 --- /dev/null +++ b/jdk/test/sun/security/ec/TestEC.policy @@ -0,0 +1,3 @@ +grant codebase "file:${test.classes}/*" { + permission java.security.AllPermission; +}; diff --git a/jdk/test/sun/security/pkcs/pkcs7/PKCS7VerifyTest.java b/jdk/test/sun/security/pkcs/pkcs7/PKCS7VerifyTest.java index 868bdc7bc51..02a8f48138f 100644 --- a/jdk/test/sun/security/pkcs/pkcs7/PKCS7VerifyTest.java +++ b/jdk/test/sun/security/pkcs/pkcs7/PKCS7VerifyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @summary Read signed data in one or more PKCS7 objects from individual files, * verify SignerInfos and certificate chain. * @modules java.base/sun.security.pkcs - * @run main PKCS7VerifyTest PKCS7TEST.DSA.base64 - * @run main PKCS7VerifyTest PKCS7TEST.DSA.base64 PKCS7TEST.SF + * @run main/othervm PKCS7VerifyTest PKCS7TEST.DSA.base64 + * @run main/othervm PKCS7VerifyTest PKCS7TEST.DSA.base64 PKCS7TEST.SF */ import java.io.ByteArrayInputStream; import java.io.File; @@ -36,6 +36,7 @@ import java.io.FileInputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.Security; import java.security.cert.X509Certificate; import java.util.Base64; import java.util.HashMap; @@ -55,6 +56,8 @@ public class PKCS7VerifyTest { throw new RuntimeException("usage: java JarVerify "); } + Security.setProperty("jdk.jar.disabledAlgorithms", ""); + // The command " java PKCS7VerifyTest file1 [file2] " // treats file1 as containing the DER encoding of a PKCS7 signed data // object. If file2 is absent, the program verifies that some signature diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java index 3752baba8da..1724fd300d9 100644 --- a/jdk/test/sun/security/pkcs11/PKCS11Test.java +++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java @@ -47,6 +47,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.Set; @@ -112,7 +113,7 @@ public abstract class PKCS11Test { found = true; break; } - } catch (Exception e) { + } catch (Exception | ServiceConfigurationError e) { // ignore and move on to the next one } } @@ -299,11 +300,12 @@ public abstract class PKCS11Test { + props.getProperty("os.arch") + "-" + props.getProperty("sun.arch.data.model"); String[] nssLibDirs = osMap.get(osid); if (nssLibDirs == null) { - System.out.println("Unsupported OS, skipping: " + osid); + System.out.println("Warning: unsupported OS: " + osid + + ", please initialize NSS librarys location firstly, skipping test"); return null; } if (nssLibDirs.length == 0) { - System.out.println("NSS not supported on this platform, skipping test"); + System.out.println("Warning: NSS not supported on this platform, skipping test"); return null; } String nssLibDir = null; @@ -315,6 +317,10 @@ public abstract class PKCS11Test { break; } } + if (nssLibDir == null) { + System.out.println("Warning: can't find NSS librarys on this machine, skipping test"); + return null; + } return nssLibDir; } @@ -624,6 +630,11 @@ public abstract class PKCS11Test { PKCS11_BASE + "/nss/lib/windows-amd64/".replace('/', SEP)}); osMap.put("MacOSX-x86_64-64", new String[]{ PKCS11_BASE + "/nss/lib/macosx-x86_64/"}); + osMap.put("Linux-arm-32", new String[]{ + "/usr/lib/arm-linux-gnueabi/nss/", + "/usr/lib/arm-linux-gnueabihf/nss/"}); + osMap.put("Linux-aarch64-64", new String[]{ + "/usr/lib/aarch64-linux-gnu/nss/"}); } private final static char[] hexDigits = "0123456789abcdef".toCharArray(); diff --git a/jdk/test/sun/security/tools/jarsigner/JarSigningNonAscii.java b/jdk/test/sun/security/tools/jarsigner/JarSigningNonAscii.java index ee54b45fe67..00094d5fbf1 100644 --- a/jdk/test/sun/security/tools/jarsigner/JarSigningNonAscii.java +++ b/jdk/test/sun/security/tools/jarsigner/JarSigningNonAscii.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,12 @@ * @bug 4924188 * @summary sign a JAR file that has entry names with non-ASCII characters. * @modules jdk.jartool/sun.security.tools.jarsigner + * @run main/othervm JarSigningNonAscii */ import sun.security.tools.*; import java.io.*; +import java.security.Security; import java.util.*; import java.util.jar.*; import java.security.cert.Certificate; @@ -40,6 +42,7 @@ public class JarSigningNonAscii { private static String keystore; public static void main(String[] args) throws Exception { + Security.setProperty("jdk.jar.disabledAlgorithms", ""); String srcDir = System.getProperty("test.src", "."); String destDir = System.getProperty("test.classes", "."); diff --git a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java index 0c597d467f2..e2ac09bd9e6 100644 --- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java +++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java @@ -22,25 +22,29 @@ */ import com.sun.net.httpserver.*; -import java.io.BufferedReader; import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; import java.math.BigInteger; import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; +import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.Locale; +import jdk.testlibrary.*; +import jdk.testlibrary.JarUtils; import sun.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS9Attribute; @@ -52,11 +56,22 @@ import sun.security.util.ObjectIdentifier; import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; +/* + * @test + * @bug 6543842 6543440 6939248 8009636 8024302 8163304 + * @summary checking response of timestamp + * @modules java.base/sun.security.pkcs + * java.base/sun.security.timestamp + * java.base/sun.security.x509 + * java.base/sun.security.util + * java.base/sun.security.tools.keytool + * @library /lib/testlibrary + * @run main/timeout=600 TimestampCheck + */ public class TimestampCheck { - static final String TSKS = "tsks"; - static final String JAR = "old.jar"; - static final String defaultPolicyId = "2.3.4.5"; + static final String defaultPolicyId = "2.3.4"; + static String host = null; static class Handler implements HttpHandler, AutoCloseable { @@ -75,11 +90,7 @@ public class TimestampCheck { t.getRequestBody().read(input); try { - int path = 0; - if (t.getRequestURI().getPath().length() > 1) { - path = Integer.parseInt( - t.getRequestURI().getPath().substring(1)); - } + String path = t.getRequestURI().getPath().substring(1); byte[] output = sign(input, path); Headers out = t.getResponseHeaders(); out.set("Content-Type", "application/timestamp-reply"); @@ -97,24 +108,10 @@ public class TimestampCheck { /** * @param input The data to sign * @param path different cases to simulate, impl on URL path - * 0: normal - * 1: Missing nonce - * 2: Different nonce - * 3: Bad digets octets in messageImprint - * 4: Different algorithmId in messageImprint - * 5: whole chain in cert set - * 6: extension is missing - * 7: extension is non-critical - * 8: extension does not have timestamping - * 9: no cert in response - * 10: normal - * 11: always return default policy id - * 12: normal - * otherwise: normal * @returns the signed */ - byte[] sign(byte[] input, int path) throws Exception { - // Read TSRequest + byte[] sign(byte[] input, String path) throws Exception { + DerValue value = new DerValue(input); System.err.println("\nIncoming Request\n==================="); System.err.println("Version: " + value.data.getInteger()); @@ -138,36 +135,33 @@ public class TimestampCheck { } } - // Write TSResponse System.err.println("\nResponse\n==================="); - KeyStore ks = KeyStore.getInstance("JKS"); - try (FileInputStream fis = new FileInputStream(keystore)) { - ks.load(fis, "changeit".toCharArray()); - } + KeyStore ks = KeyStore.getInstance( + new File(keystore), "changeit".toCharArray()); String alias = "ts"; - if (path == 6) alias = "tsbad1"; - if (path == 7) alias = "tsbad2"; - if (path == 8) alias = "tsbad3"; + if (path.startsWith("bad") || path.equals("weak")) { + alias = "ts" + path; + } - if (path == 11) { + if (path.equals("diffpolicy")) { policyId = new ObjectIdentifier(defaultPolicyId); } DerOutputStream statusInfo = new DerOutputStream(); statusInfo.putInteger(0); - DerOutputStream token = new DerOutputStream(); AlgorithmId[] algorithms = {aid}; Certificate[] chain = ks.getCertificateChain(alias); - X509Certificate[] signerCertificateChain = null; + X509Certificate[] signerCertificateChain; X509Certificate signer = (X509Certificate)chain[0]; - if (path == 5) { // Only case 5 uses full chain + + if (path.equals("fullchain")) { // Only case 5 uses full chain signerCertificateChain = new X509Certificate[chain.length]; for (int i=0; i extra) + throws Throwable { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner") + .addVMArg("-Duser.language=en") + .addVMArg("-Duser.country=US") + .addToolArg("-keystore") + .addToolArg("tsks") + .addToolArg("-storepass") + .addToolArg("changeit"); + for (String s : extra) { + if (s.startsWith("-J")) { + launcher.addVMArg(s.substring(2)); + } else { + launcher.addToolArg(s); + } + } + return ProcessTools.executeCommand(launcher.getCommand()); + } + + static OutputAnalyzer verify(String file, String... extra) + throws Throwable { + List args = new ArrayList<>(); + args.add("-verify"); + args.add(file); + args.addAll(Arrays.asList(extra)); + return jarsigner(args); + } + + static void checkBadKU(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldContain("re-run jarsigner with debug enabled"); + verify(file, "-verbose") + .shouldHaveExitValue(0) + .shouldContain("Signed by") + .shouldContain("treated as unsigned") + .shouldContain("re-run jarsigner with debug enabled"); + verify(file, "-J-Djava.security.debug=jar") + .shouldHaveExitValue(0) + .shouldContain("SignatureException: Key usage restricted") + .shouldContain("treated as unsigned") + .shouldContain("re-run jarsigner with debug enabled"); + } + + static void checkWeak(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled.") + .shouldMatch("Re-run jarsigner with the -verbose option for more details"); + verify(file, "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled by") + .shouldMatch("Digest algorithm: .*weak") + .shouldMatch("Signature algorithm: .*weak") + .shouldMatch("Timestamp digest algorithm: .*weak") + .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") + .shouldMatch("Timestamp signature algorithm: .*key.*weak"); + verify(file, "-J-Djava.security.debug=jar") + .shouldHaveExitValue(0) + .shouldMatch("SignatureException:.*Disabled"); + } + static void checkTimestamp(String file, String policyId, String digestAlg) throws Exception { try (JarFile jf = new JarFile(file)) { @@ -365,41 +473,62 @@ public class TimestampCheck { } } - /** - * @param cmd the command line (with a hole to plug in) - * @param path the path in the URL, i.e, http://localhost/path - * @param expected if this command should succeed - */ - static void jarsigner(String cmd, int path, boolean expected) - throws Exception { - System.err.println("Test " + path); - Process p = Runtime.getRuntime().exec(String.format(Locale.ROOT,cmd, path, path)); - BufferedReader reader = new BufferedReader( - new InputStreamReader(p.getErrorStream())); - while (true) { - String s = reader.readLine(); - if (s == null) break; - System.err.println(s); - } + static int which = 0; - // Will not see noTimestamp warning - boolean seeWarning = false; - reader = new BufferedReader( - new InputStreamReader(p.getInputStream())); - while (true) { - String s = reader.readLine(); - if (s == null) break; - System.err.println(s); - if (s.indexOf("Warning:") >= 0) { - seeWarning = true; - } + /** + * @param extra more args given to jarsigner + */ + static OutputAnalyzer sign(String path, String... extra) + throws Throwable { + which++; + System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra)); + List args = List.of("-J-Djava.security.egd=file:/dev/./urandom", + "-debug", "-signedjar", path + ".jar", "old.jar", + path.equals("badku") ? "badku" : "old"); + args = new ArrayList<>(args); + if (!path.equals("none") && !path.equals("badku")) { + args.add("-tsa"); + args.add(host + path); } - int result = p.waitFor(); - if (expected && result != 0 || !expected && result == 0) { - throw new Exception("Failed"); - } - if (seeWarning) { - throw new Exception("See warning"); + args.addAll(Arrays.asList(extra)); + return jarsigner(args); + } + + static void prepare() throws Exception { + jdk.testlibrary.JarUtils.createJar("old.jar", "A"); + Files.deleteIfExists(Paths.get("tsks")); + keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); + keytool("-alias old -genkeypair -dname CN=old"); + keytool("-alias badku -genkeypair -dname CN=badku"); + keytool("-alias ts -genkeypair -dname CN=ts"); + keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1"); + keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1"); + keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2"); + keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3"); + + gencert("old"); + gencert("badku", "-ext ku:critical=keyAgreement"); + gencert("ts", "-ext eku:critical=ts"); + gencert("tsweak", "-ext eku:critical=ts"); + gencert("tsbad1"); + gencert("tsbad2", "-ext eku=ts"); + gencert("tsbad3", "-ext eku:critical=cs"); + } + + static void gencert(String alias, String... extra) throws Exception { + keytool("-alias " + alias + " -certreq -file " + alias + ".req"); + String genCmd = "-gencert -alias ca -infile " + + alias + ".req -outfile " + alias + ".cert"; + for (String s : extra) { + genCmd += " " + s; } + keytool(genCmd); + keytool("-alias " + alias + " -importcert -file " + alias + ".cert"); + } + + static void keytool(String cmd) throws Exception { + cmd = "-keystore tsks -storepass changeit -keypass changeit " + + "-keyalg rsa -validity 200 " + cmd; + sun.security.tools.keytool.Main.main(cmd.split(" ")); } } diff --git a/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java b/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java index 6163e6e09d2..de225b2bcb3 100644 --- a/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java +++ b/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java @@ -31,6 +31,7 @@ import jdk.testlibrary.JarUtils; * @library /lib/testlibrary warnings * @modules java.base/sun.security.pkcs * java.base/sun.security.timestamp + * java.base/sun.security.tools.keytool * java.base/sun.security.util * java.base/sun.security.x509 * java.management diff --git a/jdk/test/sun/security/tools/jarsigner/ts.sh b/jdk/test/sun/security/tools/jarsigner/ts.sh deleted file mode 100644 index 925377ca999..00000000000 --- a/jdk/test/sun/security/tools/jarsigner/ts.sh +++ /dev/null @@ -1,103 +0,0 @@ -# -# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 6543842 6543440 6939248 8009636 8024302 -# @summary checking response of timestamp -# @modules java.base/sun.security.pkcs -# java.base/sun.security.timestamp -# java.base/sun.security.x509 -# java.base/sun.security.util -# -# @run shell/timeout=600 ts.sh - -# Run for a long time because jarsigner with timestamp needs to create a -# 64-bit random number and it might be extremely slow on a machine with -# not enough entropy pool - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - ;; -esac - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -JAR="${TESTJAVA}${FS}bin${FS}jar ${TESTTOOLVMOPTS}" -JAVA="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS}" -JAVAC="${TESTJAVA}${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}" -KT="${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200" - -rm tsks -echo Nothing > A -rm old.jar -$JAR cvf old.jar A - -# ca is CA -# old is signer for code -# ts is signer for timestamp -# tsbad1 has no extendedKeyUsage -# tsbad2's extendedKeyUsage is non-critical -# tsbad3's extendedKeyUsage has no timestamping - -$KT -alias ca -genkeypair -ext bc -dname CN=CA -$KT -alias old -genkeypair -dname CN=old -$KT -alias ts -genkeypair -dname CN=ts -$KT -alias tsbad1 -genkeypair -dname CN=tsbad1 -$KT -alias tsbad2 -genkeypair -dname CN=tsbad2 -$KT -alias tsbad3 -genkeypair -dname CN=tsbad3 - -$KT -alias old -certreq | \ - $KT -alias ca -gencert | \ - $KT -alias old -importcert -$KT -alias ts -certreq | \ - $KT -alias ca -gencert -ext eku:critical=ts | \ - $KT -alias ts -importcert -$KT -alias tsbad1 -certreq | \ - $KT -alias ca -gencert | \ - $KT -alias tsbad1 -importcert -$KT -alias tsbad2 -certreq | \ - $KT -alias ca -gencert -ext eku=ts | \ - $KT -alias tsbad2 -importcert -$KT -alias tsbad3 -certreq | \ - $KT -alias ca -gencert -ext eku:critical=cs | \ - $KT -alias tsbad3 -importcert - -EXTRAOPTS="--add-exports java.base/sun.security.pkcs=ALL-UNNAMED \ - --add-exports java.base/sun.security.timestamp=ALL-UNNAMED \ - --add-exports java.base/sun.security.x509=ALL-UNNAMED \ - --add-exports java.base/sun.security.util=ALL-UNNAMED" -$JAVAC ${EXTRAOPTS} -d . ${TESTSRC}/TimestampCheck.java -$JAVA ${TESTVMOPTS} ${EXTRAOPTS} "-Dtest.tool.vm.opts=${TESTTOOLVMOPTS}" TimestampCheck - diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh index b2102ef6a62..4e99fcd8adb 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh index b104e965ddf..ae36204249b 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh index 4b989ef2de1..67a8176fe9d 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh @@ -33,14 +33,14 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 fi rm -f Hello.class -${JAVAC} ${TESTSRC}/Hello.java -d . +${JAVAC} ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} ${TESTSRC}/Hello.java -d . # we check whether classpath setting for app classes # work with jrunscript. Script should be able to diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh index 97c62a261f9..7b3510c4af3 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh index 8c402a316ea..6be1e9132c6 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh index ab4cb16dc13..b95273c937b 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/tools/jar/ChangeDir.java b/jdk/test/tools/jar/ChangeDir.java index 7d3516bcba7..374b481bd77 100644 --- a/jdk/test/tools/jar/ChangeDir.java +++ b/jdk/test/tools/jar/ChangeDir.java @@ -24,7 +24,7 @@ /** * @test * @bug 4806786 8023113 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar -C doesn't ignore multiple // in path */ @@ -32,10 +32,15 @@ import java.io.*; import java.nio.file.*; import java.util.*; import java.util.jar.*; +import java.util.spi.ToolProvider; import java.util.stream.Stream; -import sun.tools.jar.Main; public class ChangeDir { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + private final static String jarName = "test.jar"; private final static String fileName = "hello.txt"; @@ -88,8 +93,9 @@ public class ChangeDir { argList.add(topDir.toString() + sep + "a" + sep + sep + "b"); // Note double 'sep' is intentional argList.add(fileName); - Main jarTool = new Main(System.out, System.err, "jar"); - if (!jarTool.run(argList.toArray(new String[argList.size()]))) { + int rc = JAR_TOOL.run(System.out, System.err, + argList.toArray(new String[argList.size()])); + if (rc != 0) { fail("Could not create jar file."); } diff --git a/jdk/test/tools/jar/InputFilesTest.java b/jdk/test/tools/jar/InputFilesTest.java index 7feaa533f93..ac5b3b29f94 100644 --- a/jdk/test/tools/jar/InputFilesTest.java +++ b/jdk/test/tools/jar/InputFilesTest.java @@ -29,7 +29,7 @@ * duplicates that sometimes cause exceptions and other times do not, * demonstrating identical behavior to JDK 8 jar tool. * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @build jdk.testlibrary.FileUtils * @run testng InputFilesTest */ @@ -47,12 +47,18 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import java.util.zip.ZipException; import jdk.testlibrary.FileUtils; public class InputFilesTest { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + private final String nl = System.lineSeparator(); private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); private final PrintStream out = new PrintStream(baos); @@ -195,9 +201,9 @@ public class InputFilesTest { PrintStream err = new PrintStream(baes); PrintStream saveErr = System.err; System.setErr(err); - boolean ok = new sun.tools.jar.Main(out, err, "jar").run(cmdline.split(" +")); + int rc = JAR_TOOL.run(out, err, cmdline.split(" +")); System.setErr(saveErr); - if (!ok) { + if (rc != 0) { String s = baes.toString(); if (s.startsWith("java.util.zip.ZipException: duplicate entry: ")) { throw new ZipException(s); diff --git a/jdk/test/tools/jar/JarBackSlash.java b/jdk/test/tools/jar/JarBackSlash.java index 565606b8f3f..74c561d1fe6 100644 --- a/jdk/test/tools/jar/JarBackSlash.java +++ b/jdk/test/tools/jar/JarBackSlash.java @@ -28,7 +28,7 @@ /* * @test * @bug 7201156 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar tool fails to convert file separation characters for list and extract * @author Sean Chou */ @@ -43,10 +43,13 @@ import java.util.ArrayList; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; - -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class JarBackSlash { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); // used construct an entry JarBackSlash/dir/file.txt private static String JARBACKSLASH = "JarBackSlash"; @@ -78,8 +81,8 @@ public class JarBackSlash { PipedInputStream pipedInput = new PipedInputStream(pipedOutput); PrintStream out = new PrintStream(pipedOutput); - Main jarTool = new Main(out, System.err, "jar"); - if (!jarTool.run(jarArgs)) { + int rc = JAR_TOOL.run(out, System.err, jarArgs); + if (rc != 0) { fail("Could not list jar file."); } @@ -101,8 +104,8 @@ public class JarBackSlash { PipedInputStream pipedInput = new PipedInputStream(pipedOutput); PrintStream out = new PrintStream(pipedOutput); - Main jarTool = new Main(out, System.err, "jar"); - if (!jarTool.run(jarArgs)) { + int rc = JAR_TOOL.run(out, System.err, jarArgs); + if (rc != 0) { fail("Could not list jar file."); } diff --git a/jdk/test/tools/jar/JarEntryTime.java b/jdk/test/tools/jar/JarEntryTime.java index 1985bb1ab66..80fd65fba5c 100644 --- a/jdk/test/tools/jar/JarEntryTime.java +++ b/jdk/test/tools/jar/JarEntryTime.java @@ -24,7 +24,7 @@ /** * @test * @bug 4225317 6969651 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Check extracted files have date as per those in the .jar file */ @@ -33,9 +33,14 @@ import java.io.PrintWriter; import java.nio.file.attribute.FileTime; import java.util.Date; import java.util.TimeZone; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class JarEntryTime { + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + // ZipEntry's mod date has 2 seconds precision: give extra time to // allow for e.g. rounding/truncation and networked/samba drives. @@ -114,10 +119,8 @@ public class JarEntryTime { check(fileInner.setLastModified(earlier)); // Make a jar file from that directory structure - Main jartool = new Main(System.out, System.err, "jar"); - check(jartool.run(new String[] { - "cf", - jarFile.getName(), dirOuter.getName() } )); + check(JAR_TOOL.run(System.out, System.err, + "cf", jarFile.getName(), dirOuter.getName()) == 0); check(jarFile.exists()); check(cleanup(dirInner)); @@ -142,7 +145,6 @@ public class JarEntryTime { final long start = testFile.lastModified(); // Extract and check the last modified values are the current times. - // See sun.tools.jar.Main extractJar(jarFile, true); try (PrintWriter pw = new PrintWriter(testFile)) { diff --git a/jdk/test/tools/jar/ReleaseBeforeFiles.java b/jdk/test/tools/jar/ReleaseBeforeFiles.java new file mode 100644 index 00000000000..56c27107a1b --- /dev/null +++ b/jdk/test/tools/jar/ReleaseBeforeFiles.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8167237 + * @summary test that both old style command line options and new gnu style + * command line options work with the --release option whether or + * not the --release option is preceded by a file name. + * @library /lib/testlibrary + * @modules jdk.jartool/sun.tools.jar + * @build jdk.testlibrary.FileUtils + * @run testng ReleaseBeforeFiles + */ + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.stream.Stream; + +import jdk.testlibrary.FileUtils; + +public class ReleaseBeforeFiles { + private Runnable onCompletion; + + @BeforeMethod + public void reset() { + onCompletion = null; + } + + @AfterMethod + public void run() { + if (onCompletion != null) { + onCompletion.run(); + } + } + + @Test // passes before bug fix + public void test1() throws IOException { + mkdir("test1"); + touch("test1/testfile1"); + jar("cf test.jar --release 9 test1"); + jar("tf test.jar"); + rm("test.jar test1"); + } + + @Test // fails before bug fix + public void test2() throws IOException { + System.out.println("====="); + mkdir("test1"); + touch("test1/testfile1"); + onCompletion = () -> rm("test.jar test1"); + jar("--create --file=test.jar --release 9 test1"); + jar("tf test.jar"); + } + + @Test // passes before bug fix + public void test3() throws IOException { + System.out.println("====="); + mkdir("test1"); + touch("test1/testfile1"); + jar("-cf test.jar -C test1 ."); + jar("-uf test.jar --release 9 -C test1 ."); + jar("tf test.jar"); + rm("test.jar test1"); + } + + @Test // fails before bug fix + public void test4() throws IOException { + System.out.println("====="); + mkdir("test1"); + touch("test1/testfile1"); + onCompletion = () -> rm("test.jar test1"); + jar("--create --file=test.jar -C test1 ."); + jar("--update --file=test.jar --release 9 -C test1 ."); + jar("tf test.jar"); + } + + @Test // passes before bug fix since test2 precedes --release 9 + public void test5() throws IOException { + System.out.println("====="); + mkdir("test1 test2"); + touch("test1/testfile1 test2/testfile2"); + jar("--create --file=test.jar -C test1 ."); + jar("--update --file=test.jar test2 --release 9 -C test1 ."); + jar("tf test.jar"); + rm("test.jar test1 test2"); + } + + private Stream mkpath(String... args) { + return Arrays.stream(args).map(d -> Paths.get(".", d.split("/"))); + } + + private void mkdir(String cmdline) { + System.out.println("mkdir -p " + cmdline); + mkpath(cmdline.split(" +")).forEach(p -> { + try { + Files.createDirectories(p); + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + + private void touch(String cmdline) { + System.out.println("touch " + cmdline); + mkpath(cmdline.split(" +")).forEach(p -> { + try { + Files.createFile(p); + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + + private void rm(String cmdline) { + System.out.println("rm -rf " + cmdline); + mkpath(cmdline.split(" +")).forEach(p -> { + try { + if (Files.isDirectory(p)) { + FileUtils.deleteFileTreeWithRetry(p); + } else { + FileUtils.deleteFileIfExistsWithRetry(p); + } + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + + private void jar(String cmdline) throws IOException { + System.out.println("jar " + cmdline); + boolean ok = new sun.tools.jar.Main(System.out, System.err, "jar") + .run(cmdline.split(" +")); + Assert.assertTrue(ok); + } +} diff --git a/jdk/test/tools/jar/UpdateJar.java b/jdk/test/tools/jar/UpdateJar.java index 524189bb841..c8e87bbc198 100644 --- a/jdk/test/tools/jar/UpdateJar.java +++ b/jdk/test/tools/jar/UpdateJar.java @@ -24,7 +24,7 @@ /** * @test * @bug 7175845 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar -uf should not change file permission */ @@ -32,9 +32,13 @@ import java.io.*; import java.nio.file.*; import java.nio.file.attribute.*; import java.util.Set; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class UpdateJar { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); private static void cleanup(String... fnames) throws Throwable { for (String fname : fnames) { @@ -55,12 +59,12 @@ public class UpdateJar { fos1.write(0); } String[] jarArgs = new String[] {"cfM0", jar, e0}; - if (!new Main(System.out, System.err, "jar").run(jarArgs)) { + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { fail("Could not create jar file."); } Set pm = Files.getPosixFilePermissions(Paths.get(jar)); jarArgs = new String[] {"uf", jar, e1}; - if (!new Main(System.out, System.err, "jar").run(jarArgs)) { + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { fail("Could not create jar file."); } equal(pm, Files.getPosixFilePermissions(Paths.get(jar))); diff --git a/jdk/test/tools/jar/UpdateManifest.java b/jdk/test/tools/jar/UpdateManifest.java index d07674cab17..31dbee5c68d 100644 --- a/jdk/test/tools/jar/UpdateManifest.java +++ b/jdk/test/tools/jar/UpdateManifest.java @@ -24,7 +24,7 @@ /** * @test * @bug 6434207 6442687 6984046 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Ensure that jar ufm actually updates the * existing jar file's manifest with contents of the * manifest file. @@ -32,14 +32,19 @@ import java.io.*; import java.util.logging.*; +import java.util.spi.ToolProvider; import java.util.zip.*; -import sun.tools.jar.Main; public class UpdateManifest { static PrintStream out = System.out; static PrintStream err = System.err; static boolean debug = true; + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + static final Logger JAR_LOGGER = Logger.getLogger("java.util.jar"); public static void realMain(String[] args) throws Throwable { @@ -64,17 +69,14 @@ public class UpdateManifest { // Create a jar file, specifying a Main-Class final String jarFileName = "um-existence.jar"; new File(jarFileName).delete(); // remove pre-existing first! - Main jartool = new Main(out, err, "jar"); - boolean status = jartool.run( - new String[] { "cfe", jarFileName, "Hello", existence.getPath() }); - check(status); + int status = JAR_TOOL.run(out, err, "cfe", jarFileName, + "Hello", existence.getPath()); + check(status == 0); checkManifest(jarFileName, "Hello"); // Update that jar file by changing the Main-Class - jartool = new Main(out, err, "jar"); - status = jartool.run( - new String[] { "ufe", jarFileName, "Bye" }); - check(status); + status = JAR_TOOL.run(out, err, "ufe", jarFileName, "Bye"); + check(status == 0); checkManifest(jarFileName, "Bye"); } @@ -101,11 +103,9 @@ public class UpdateManifest { // Create a jar file final String jarFileName = "um-test.jar"; new File(jarFileName).delete(); // remove pre-existing first! - Main jartool = new Main(out, err, "jar"); - boolean status = jartool.run( - new String[] {"cfm", jarFileName, - manifestOrig.getPath(), hello.getPath() }); - check(status); + int status = JAR_TOOL.run(out, err, "cfm", jarFileName, + manifestOrig.getPath(), hello.getPath()); + check(status == 0); // Create a new manifest, to use in updating the jar file. File manifestUpdate = File.createTempFile("manifestUpdate", ".txt"); @@ -122,10 +122,9 @@ public class UpdateManifest { pw.close(); // Update jar file with manifest - jartool = new Main(out, err, "jar"); - status = jartool.run( - new String[] { "ufm", jarFileName, manifestUpdate.getPath() }); - check(status); + status = JAR_TOOL.run(out, err, "ufm", + jarFileName, manifestUpdate.getPath()); + check(status == 0); // Extract jar, and verify contents of manifest file File f = new File(jarFileName); diff --git a/jdk/test/tools/jar/index/MetaInf.java b/jdk/test/tools/jar/index/MetaInf.java index 29108c72d2f..1353acf87f3 100644 --- a/jdk/test/tools/jar/index/MetaInf.java +++ b/jdk/test/tools/jar/index/MetaInf.java @@ -24,17 +24,21 @@ /* * @test * @bug 4408526 6854795 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Index the non-meta files in META-INF, such as META-INF/services. */ import java.io.*; import java.util.Arrays; import java.util.jar.*; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; import java.util.zip.ZipFile; public class MetaInf { + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); static String jarName = "a.jar"; static String INDEX = "META-INF/INDEX.LIST"; @@ -43,7 +47,7 @@ public class MetaInf { System.getProperty("test.src") + File.separatorChar + "jarcontents"; static void run(String ... args) { - if (! new Main(System.out, System.err, "jar").run(args)) + if (JAR_TOOL.run(System.out, System.err, args) != 0) throw new Error("jar failed: args=" + Arrays.toString(args)); } diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java index 970e1371131..17dcfdec5a9 100644 --- a/jdk/test/tools/jlink/IntegrationTest.java +++ b/jdk/test/tools/jlink/IntegrationTest.java @@ -37,14 +37,14 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.function.Function; -import jdk.tools.jlink.Jlink; -import jdk.tools.jlink.Jlink.JlinkConfiguration; -import jdk.tools.jlink.Jlink.PluginsConfiguration; +import jdk.tools.jlink.internal.Jlink; import jdk.tools.jlink.builder.DefaultImageBuilder; import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePoolBuilder; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.internal.ExecutableImage; +import jdk.tools.jlink.internal.Jlink.JlinkConfiguration; +import jdk.tools.jlink.internal.Jlink.PluginsConfiguration; import jdk.tools.jlink.internal.PostProcessor; import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin; import jdk.tools.jlink.internal.plugins.StripDebugPlugin; diff --git a/jdk/test/tools/jlink/JLinkTest.java b/jdk/test/tools/jlink/JLinkTest.java index d6e9d1bca92..2215bef8ec0 100644 --- a/jdk/test/tools/jlink/JLinkTest.java +++ b/jdk/test/tools/jlink/JLinkTest.java @@ -32,13 +32,13 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.internal.PluginRepository; import tests.Helper; import tests.JImageGenerator; -import tests.JImageGenerator.InMemoryFile; /* * @test @@ -48,13 +48,17 @@ import tests.JImageGenerator.InMemoryFile; * @modules java.base/jdk.internal.jimage * jdk.jdeps/com.sun.tools.classfile * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod * jdk.jlink/jdk.tools.jimage * jdk.compiler * @build tests.* * @run main/othervm -Xmx1g JLinkTest */ public class JLinkTest { + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); + // number of built-in plugins from jdk.jlink module private static int getNumJlinkPlugins() { ModuleDescriptor desc = Plugin.class.getModule().getDescriptor(); @@ -180,7 +184,8 @@ public class JLinkTest { { // Help StringWriter writer = new StringWriter(); - jdk.tools.jlink.internal.Main.run(new String[]{"--help"}, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + JLINK_TOOL.run(pw, pw, "--help"); String output = writer.toString(); if (output.split("\n").length < 10) { System.err.println(output); @@ -202,7 +207,9 @@ public class JLinkTest { { // List plugins StringWriter writer = new StringWriter(); - jdk.tools.jlink.internal.Main.run(new String[]{"--list-plugins"}, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + + JLINK_TOOL.run(pw, pw, "--list-plugins"); String output = writer.toString(); long number = Stream.of(output.split("\\R")) .filter((s) -> s.matches("Plugin Name:.*")) diff --git a/jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java b/jdk/test/tools/jlink/JLinkToolProviderTest.java similarity index 51% rename from jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java rename to jdk/test/tools/jlink/JLinkToolProviderTest.java index 377cf10d6e1..1204f83703d 100644 --- a/jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java +++ b/jdk/test/tools/jlink/JLinkToolProviderTest.java @@ -21,41 +21,38 @@ * questions. */ +import java.io.PrintWriter; +import java.io.StringWriter; +import java.security.AccessControlException; +import java.util.spi.ToolProvider; + /* * @test - * @bug 8137058 - * @summary Basic test for the unsupported newConstructorForSerialization - * @modules jdk.unsupported + * @build JLinkToolProviderTest + * @run main/othervm/java.security.policy=toolprovider.policy JLinkToolProviderTest */ +public class JLinkToolProviderTest { + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); -import java.lang.reflect.Constructor; -import sun.reflect.ReflectionFactory; + private static void checkJlinkOptions(String... options) { + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); -public class NewConstructorForSerialization { - - private static Constructor getConstructor(Class type) - throws NoSuchMethodException - { - ReflectionFactory factory = ReflectionFactory.getReflectionFactory(); - Constructor objectConstructor = type.getConstructor((Class[]) null); - - @SuppressWarnings("unchecked") - Constructor c = (Constructor) factory - .newConstructorForSerialization(type, objectConstructor); - return c; + try { + JLINK_TOOL.run(pw, pw, options); + throw new AssertionError("SecurityException should have been thrown!"); + } catch (AccessControlException ace) { + if (! ace.getPermission().getClass().getName().contains("JlinkPermission")) { + throw new AssertionError("expected JlinkPermission check failure"); + } + } } public static void main(String[] args) throws Exception { - System.out.println(getConstructor(Object.class).newInstance()); - System.out.println(getConstructor(Foo.class).newInstance()); - System.out.println(getConstructor(Bar.class).newInstance()); - } - - static class Foo { - public Foo() { } - } - - static class Bar extends Foo { - public Bar() { } + checkJlinkOptions("--help"); + checkJlinkOptions("--list-plugins"); } } diff --git a/jdk/test/tools/jlink/SecurityTest.java b/jdk/test/tools/jlink/SecurityTest.java index dbf593bccc0..7aff0c220c7 100644 --- a/jdk/test/tools/jlink/SecurityTest.java +++ b/jdk/test/tools/jlink/SecurityTest.java @@ -25,12 +25,12 @@ * @test * @summary Test JlinkPermission * @author Jean-Francois Denise - * @modules jdk.jlink/jdk.tools.jlink + * @modules jdk.jlink/jdk.tools.jlink.internal * @run main/othervm SecurityTest */ import java.security.AccessControlException; -import jdk.tools.jlink.Jlink; +import jdk.tools.jlink.internal.Jlink; public class SecurityTest { diff --git a/jdk/test/tools/jlink/basic/BasicTest.java b/jdk/test/tools/jlink/basic/BasicTest.java index 780cbca9cbc..6ddc4a190f9 100644 --- a/jdk/test/tools/jlink/basic/BasicTest.java +++ b/jdk/test/tools/jlink/basic/BasicTest.java @@ -27,8 +27,7 @@ * @author Andrei Eremeev * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod + * jdk.jlink * jdk.compiler * @build jdk.testlibrary.ProcessTools * jdk.testlibrary.OutputAnalyzer @@ -44,11 +43,21 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.spi.ToolProvider; import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.ProcessTools; public class BasicTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); private final Path jdkHome = Paths.get(System.getProperty("test.jdk")); private final Path jdkMods = jdkHome.resolve("jmods"); @@ -110,20 +119,22 @@ public class BasicTest { "--add-modules", modName, "--output", image.toString()); Collections.addAll(args, options); - int rc = jdk.tools.jlink.internal.Main.run(args.toArray(new String[args.size()]), new PrintWriter(System.out)); + + PrintWriter pw = new PrintWriter(System.out); + int rc = JLINK_TOOL.run(pw, pw, args.toArray(new String[args.size()])); if (rc != 0) { throw new AssertionError("Jlink failed: rc = " + rc); } } private void runJmod(String cp, String modName) { - int rc = jdk.tools.jmod.Main.run(new String[] { + int rc = JMOD_TOOL.run(System.out, System.out, new String[] { "create", "--class-path", cp, "--module-version", "1.0", "--main-class", "jdk.test.Test", jmods.resolve(modName + ".jmod").toString(), - }, System.out); + }); if (rc != 0) { throw new AssertionError("Jmod failed: rc = " + rc); } diff --git a/jdk/test/tools/jlink/plugins/ExcludeJmodSectionPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeJmodSectionPluginTest.java new file mode 100644 index 00000000000..810a75178f2 --- /dev/null +++ b/jdk/test/tools/jlink/plugins/ExcludeJmodSectionPluginTest.java @@ -0,0 +1,340 @@ +/** + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test --no-man-pages and --no-header-files + * @library /lib/testlibrary + * @modules jdk.compiler + * jdk.jlink + * @build CompilerUtils + * @run testng ExcludeJmodSectionPluginTest + */ + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.spi.ToolProvider; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +public class ExcludeJmodSectionPluginTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); + + static final Path MODULE_PATH = Paths.get(System.getProperty("java.home"), "jmods"); + static final Path SRC_DIR = Paths.get("src"); + static final Path MODS_DIR = Paths.get("mods"); + static final Path JMODS_DIR = Paths.get("jmods"); + static final Path MAN_DIR = Paths.get("man"); + static final Path INCLUDE_DIR = Paths.get("include"); + static final Path IMAGES_DIR = Paths.get("images"); + + @BeforeTest + private void setup() throws Exception { + // build jmod files + JmodFileBuilder m1 = new JmodFileBuilder("m1"); + m1.headerFile("m1a.h"); + m1.headerFile("m1b.h"); + m1.build(); + + JmodFileBuilder m2 = new JmodFileBuilder("m2"); + m2.headerFile("m2.h"); + m2.manPage("tool2.1"); + m2.build(); + + JmodFileBuilder m3 = new JmodFileBuilder("m3"); + m3.manPage("tool3.1"); + m3.build(); + } + + private String imageDir(String dir) { + return IMAGES_DIR.resolve(dir).toString(); + } + + + @DataProvider(name = "jlinkoptions") + public Object[][] jlinkoptions() { + // options and expected header files & man pages + return new Object[][] { + { new String [] { + "test1", + "--exclude-files=/java.base/include/**,/java.base/man/**", + }, + List.of("include/m1a.h", + "include/m1b.h", + "include/m2.h", + "man/tool2.1", + "man/tool3.1") + }, + + { new String [] { + "test2", + "--no-man-pages", + "--no-header-files", + }, + List.of() + }, + + { new String[] { + "test3", + "--no-header-files", + "--exclude-files=/java.base/man/**" + }, + List.of("man/tool2.1", + "man/tool3.1") }, + + { new String [] { + "test4", + "--no-man-pages", + "--exclude-files=/java.base/include/**,/m2/include/**", + }, + List.of("include/m1a.h", + "include/m1b.h") + }, + + { new String [] { + "test5", + "--no-header-files", + "--exclude-files=/java.base/man/**,/m2/man/**" + }, + List.of("man/tool3.1") + }, + }; + } + + @Test(dataProvider = "jlinkoptions") + public void test(String[] opts, List expectedFiles) throws Exception { + if (Files.notExists(MODULE_PATH)) { + // exploded image + return; + } + + String dir = opts[0]; + List options = new ArrayList<>(); + for (int i = 1; i < opts.length; i++) { + options.add(opts[i]); + } + + String mpath = MODULE_PATH.toString() + File.pathSeparator + + JMODS_DIR.toString(); + Stream.of("--module-path", mpath, + "--add-modules", "m1,m2,m3", + "--output", imageDir(dir)) + .forEach(options::add); + + Path image = createImage(dir, options, expectedFiles); + + // check if any unexpected header file or man page + Set extraFiles = Files.walk(image, Integer.MAX_VALUE) + .filter(p -> Files.isRegularFile(p)) + .filter(p -> p.getParent().endsWith("include") || + p.getParent().endsWith("man")) + .filter(p -> { + String fn = String.format("%s/%s", + p.getParent().getFileName().toString(), + p.getFileName().toString()); + return !expectedFiles.contains(fn); + }) + .collect(Collectors.toSet()); + + if (extraFiles.size() > 0) { + System.out.println("Unexpected files: " + extraFiles.toString()); + assertTrue(extraFiles.isEmpty()); + } + } + + /** + * Test java.base's include header files + */ + @Test + public void testJavaBase() { + if (Files.notExists(MODULE_PATH)) { + // exploded image + return; + } + List options = List.of("--module-path", + MODULE_PATH.toString(), + "--add-modules", "java.base", + "--output", imageDir("base")); + createImage("base", options, + List.of("include/jni.h", "include/jvmti.h")); + + } + + private Path createImage(String outputDir, List options, + List expectedFiles) { + System.out.println("jlink " + options.toString()); + int rc = JLINK_TOOL.run(System.out, System.out, + options.toArray(new String[0])); + assertTrue(rc == 0); + + Path d = IMAGES_DIR.resolve(outputDir); + for (String fn : expectedFiles) { + Path path = d.resolve(fn); + if (Files.notExists(path)) { + throw new RuntimeException(path + " not found"); + } + } + return d; + } + + private void deleteDirectory(Path dir) throws IOException { + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException + { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException + { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } + + /** + * Builder to create JMOD file + */ + class JmodFileBuilder { + + final String name; + final Set manPages = new HashSet<>(); + final Set headerFiles = new HashSet<>(); + + JmodFileBuilder(String name) throws IOException { + this.name = name; + + Path msrc = SRC_DIR.resolve(name); + if (Files.exists(msrc)) { + deleteDirectory(msrc); + } + } + + JmodFileBuilder manPage(String filename) { + manPages.add(filename); + return this; + } + + JmodFileBuilder headerFile(String filename) { + headerFiles.add(filename); + return this; + } + + Path build() throws IOException { + compileModule(); + // create man pages + Path mdir = MAN_DIR.resolve(name); + for (String filename : manPages) { + Files.createDirectories(mdir); + Files.createFile(mdir.resolve(filename)); + } + // create header files + mdir = INCLUDE_DIR.resolve(name); + for (String filename : headerFiles) { + Files.createDirectories(mdir); + Files.createFile(mdir.resolve(filename)); + } + return createJmodFile(); + } + + void compileModule() throws IOException { + Path msrc = SRC_DIR.resolve(name); + Files.createDirectories(msrc); + Path minfo = msrc.resolve("module-info.java"); + try (BufferedWriter bw = Files.newBufferedWriter(minfo); + PrintWriter writer = new PrintWriter(bw)) { + writer.format("module %s { }%n", name); + } + + assertTrue(CompilerUtils.compile(msrc, MODS_DIR, + "--module-source-path", + SRC_DIR.toString())); + } + + Path createJmodFile() throws IOException { + Path mclasses = MODS_DIR.resolve(name); + Files.createDirectories(JMODS_DIR); + Path outfile = JMODS_DIR.resolve(name + ".jmod"); + List args = new ArrayList<>(); + args.add("create"); + // add classes + args.add("--class-path"); + args.add(mclasses.toString()); + // man pages + if (manPages.size() > 0) { + args.add("--man-pages"); + args.add(MAN_DIR.resolve(name).toString()); + } + // header files + if (headerFiles.size() > 0) { + args.add("--header-files"); + args.add(INCLUDE_DIR.resolve(name).toString()); + } + args.add(outfile.toString()); + + if (Files.exists(outfile)) + Files.delete(outfile); + + System.out.println("jmod " + + args.stream().collect(Collectors.joining(" "))); + + int rc = JMOD_TOOL.run(System.out, System.out, + args.toArray(new String[args.size()])); + if (rc != 0) { + throw new AssertionError("jmod failed: rc = " + rc); + } + return outfile; + } + } +} diff --git a/jdk/test/tools/jlink/plugins/LastSorterTest.java b/jdk/test/tools/jlink/plugins/LastSorterTest.java index b9bd0eeb6ef..0415a431eef 100644 --- a/jdk/test/tools/jlink/plugins/LastSorterTest.java +++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java @@ -37,11 +37,11 @@ import java.util.List; import java.util.Map; import jdk.tools.jlink.internal.ImagePluginConfiguration; -import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ImagePluginStack; +import jdk.tools.jlink.internal.Jlink; +import jdk.tools.jlink.internal.Jlink.PluginsConfiguration; +import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ResourcePoolManager; -import jdk.tools.jlink.Jlink; -import jdk.tools.jlink.Jlink.PluginsConfiguration; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePoolBuilder; diff --git a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java index 12eb55f3e4c..7c7dc268697 100644 --- a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java +++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java @@ -36,11 +36,11 @@ import java.util.List; import java.util.Map; import jdk.tools.jlink.internal.ImagePluginConfiguration; +import jdk.tools.jlink.internal.Jlink; +import jdk.tools.jlink.internal.Jlink.PluginsConfiguration; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.internal.ResourcePoolManager; -import jdk.tools.jlink.Jlink; -import jdk.tools.jlink.Jlink.PluginsConfiguration; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePoolBuilder; diff --git a/jdk/test/tools/jlink/plugins/PrevisitorTest.java b/jdk/test/tools/jlink/plugins/PrevisitorTest.java index b83323170ab..8c42075d6c3 100644 --- a/jdk/test/tools/jlink/plugins/PrevisitorTest.java +++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java @@ -40,13 +40,13 @@ import java.util.Optional; import java.util.stream.Collectors; import jdk.tools.jlink.internal.ImagePluginConfiguration; +import jdk.tools.jlink.internal.Jlink; import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.internal.ResourcePoolManager; import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl; import jdk.tools.jlink.internal.ResourcePrevisitor; import jdk.tools.jlink.internal.StringTable; -import jdk.tools.jlink.Jlink; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePoolBuilder; diff --git a/jdk/test/tools/jlink/toolprovider.policy b/jdk/test/tools/jlink/toolprovider.policy new file mode 100644 index 00000000000..e89913b9f24 --- /dev/null +++ b/jdk/test/tools/jlink/toolprovider.policy @@ -0,0 +1,2 @@ +grant { +}; diff --git a/jdk/test/tools/jmod/JmodNegativeTest.java b/jdk/test/tools/jmod/JmodNegativeTest.java index 317587f5fb5..02a3791dfac 100644 --- a/jdk/test/tools/jmod/JmodNegativeTest.java +++ b/jdk/test/tools/jmod/JmodNegativeTest.java @@ -24,8 +24,8 @@ /* * @test * @library /lib/testlibrary - * @modules jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodNegativeTest * @summary Negative tests for jmod @@ -39,6 +39,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.spi.ToolProvider; import java.util.zip.ZipOutputStream; import jdk.testlibrary.FileUtils; import org.testng.annotations.BeforeTest; @@ -51,6 +52,11 @@ import static org.testng.Assert.assertTrue; public class JmodNegativeTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + static final String TEST_SRC = System.getProperty("test.src", "."); static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); static final Path EXPLODED_DIR = Paths.get("build"); @@ -515,7 +521,7 @@ public class JmodNegativeTest { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.out.println("jmod " + Arrays.asList(args)); - int ec = jdk.tools.jmod.Main.run(args, ps); + int ec = JMOD_TOOL.run(ps, ps, args); return new JmodResult(ec, new String(baos.toByteArray(), UTF_8)); } diff --git a/jdk/test/tools/jmod/JmodTest.java b/jdk/test/tools/jmod/JmodTest.java index 064ba585297..5be6a692daf 100644 --- a/jdk/test/tools/jmod/JmodTest.java +++ b/jdk/test/tools/jmod/JmodTest.java @@ -24,8 +24,8 @@ /* * @test * @library /lib/testlibrary - * @modules jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodTest * @summary Basic test for jmod @@ -38,6 +38,7 @@ import java.nio.file.*; import java.util.*; import java.util.function.Consumer; import java.util.regex.Pattern; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.testlibrary.FileUtils; import org.testng.annotations.BeforeTest; @@ -51,6 +52,11 @@ import static org.testng.Assert.*; public class JmodTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + static final String TEST_SRC = System.getProperty("test.src", "."); static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); static final Path EXPLODED_DIR = Paths.get("build"); @@ -479,7 +485,7 @@ public class JmodTest { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.out.println("jmod " + Arrays.asList(args)); - int ec = jdk.tools.jmod.Main.run(args, ps); + int ec = JMOD_TOOL.run(ps, ps, args); return new JmodResult(ec, new String(baos.toByteArray(), UTF_8)); } diff --git a/jdk/test/tools/jmod/hashes/HashesTest.java b/jdk/test/tools/jmod/hashes/HashesTest.java index 616d393b97a..e01ecdb8046 100644 --- a/jdk/test/tools/jmod/hashes/HashesTest.java +++ b/jdk/test/tools/jmod/hashes/HashesTest.java @@ -27,8 +27,7 @@ * @author Andrei Eremeev * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod + * jdk.jlink * jdk.compiler * @build CompilerUtils * @run testng HashesTest @@ -53,6 +52,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.spi.ToolProvider; import java.util.stream.Collectors; import jdk.internal.module.ConfigurableModuleFinder; @@ -63,6 +63,10 @@ import org.testng.annotations.Test; import static org.testng.Assert.*; public class HashesTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); private final Path testSrc = Paths.get(System.getProperty("test.src")); private final Path modSrc = testSrc.resolve("src"); @@ -204,7 +208,7 @@ public class HashesTest { } private void runJmod(List args) { - int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out); + int rc = JMOD_TOOL.run(System.out, System.out, args.toArray(new String[args.size()])); System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" "))); if (rc != 0) { throw new AssertionError("Jmod failed: rc = " + rc); diff --git a/jdk/test/tools/launcher/modules/basic/BasicTest.java b/jdk/test/tools/launcher/modules/basic/BasicTest.java index 233fa29e00b..3256f354c78 100644 --- a/jdk/test/tools/launcher/modules/basic/BasicTest.java +++ b/jdk/test/tools/launcher/modules/basic/BasicTest.java @@ -24,9 +24,9 @@ /** * @test * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar - * jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jartool + * jdk.jlink * @build BasicTest CompilerUtils jdk.testlibrary.* * @run testng BasicTest * @summary Basic test of starting an application as a module @@ -36,6 +36,7 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.spi.ToolProvider; import jdk.testlibrary.ProcessTools; @@ -46,6 +47,14 @@ import static org.testng.Assert.*; @Test public class BasicTest { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + private static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); @@ -132,10 +141,8 @@ public class BasicTest { "--main-class=" + MAIN_CLASS, "-C", classes, "." }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar") - .run(args); - assertTrue(success); + int rc = JAR_TOOL.run(System.out, System.out, args); + assertTrue(rc == 0); // java --module-path mlib -module $TESTMODULE int exitValue = exec("--module-path", dir.toString(), @@ -164,8 +171,8 @@ public class BasicTest { "--main-class", MAIN_CLASS, jmod }; - jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask(); - assertEquals(task.run(args), 0); + + assertEquals(JMOD_TOOL.run(System.out, System.out, args), 0); // java --module-path mods --module $TESTMODULE int exitValue = exec("--module-path", dir.toString(), @@ -229,10 +236,8 @@ public class BasicTest { "--file=" + jar, "-C", classes, "." }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar") - .run(args); - assertTrue(success); + int rc = JAR_TOOL.run(System.out, System.out, args); + assertTrue(rc == 0); // java --module-path mods -m $TESTMODULE int exitValue = exec("--module-path", dir.toString(), "-m", TEST_MODULE); diff --git a/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java b/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java index acf65bc1475..fe9a293be57 100644 --- a/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java +++ b/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java @@ -26,7 +26,7 @@ * @bug 8159596 * @library /lib/testlibrary * @modules jdk.compiler - * jdk.jartool/sun.tools.jar + * jdk.jartool * @build DryRunTest CompilerUtils jdk.testlibrary.ProcessTools * @run testng DryRunTest * @summary Test java --dry-run @@ -37,6 +37,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.spi.ToolProvider; import jdk.testlibrary.ProcessTools; @@ -78,8 +79,8 @@ public class DryRunTest { Files.createDirectories(LIBS_DIR); // create JAR files with no module-info.class - assertTrue(jar(M_MODULE, "p/Lib.class")); - assertTrue(jar(TEST_MODULE, "jdk/test/Main.class")); + assertTrue(jar(M_MODULE, "p/Lib.class") == 0); + assertTrue(jar(TEST_MODULE, "jdk/test/Main.class") == 0); } /** @@ -197,7 +198,12 @@ public class DryRunTest { assertTrue(exitValue != 0); } - private static boolean jar(String name, String entries) throws IOException { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + + private static int jar(String name, String entries) throws IOException { Path jar = LIBS_DIR.resolve(name + ".jar"); // jar --create ... @@ -207,8 +213,6 @@ public class DryRunTest { "--file=" + jar, "-C", classes, entries }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar").run(args); - return success; + return JAR_TOOL.run(System.out, System.out, args); } } diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java index beaf2dbe0b6..59e7d37cbce 100644 --- a/jdk/test/tools/lib/tests/JImageGenerator.java +++ b/jdk/test/tools/lib/tests/JImageGenerator.java @@ -338,6 +338,10 @@ public class JImageGenerator { } public static class JModTask { + static final java.util.spi.ToolProvider JMOD_TOOL = + java.util.spi.ToolProvider.findFirst("jmod").orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); private final List classpath = new ArrayList<>(); private final List libs = new ArrayList<>(); @@ -477,7 +481,8 @@ public class JImageGenerator { String[] args = optionsJMod(cmd); System.err.println("jmod options: " + optionsPrettyPrint(args)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int exitCode = jdk.tools.jmod.Main.run(args, new PrintStream(baos)); + PrintStream ps = new PrintStream(baos); + int exitCode = JMOD_TOOL.run(ps, ps, args); String msg = new String(baos.toByteArray()); return new Result(exitCode, msg, output); } @@ -556,6 +561,10 @@ public class JImageGenerator { } public static class JLinkTask { + static final java.util.spi.ToolProvider JLINK_TOOL = + java.util.spi.ToolProvider.findFirst("jlink").orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); private final List jars = new ArrayList<>(); private final List jmods = new ArrayList<>(); @@ -691,7 +700,8 @@ public class JImageGenerator { String[] args = optionsJLink(); System.err.println("jlink options: " + optionsPrettyPrint(args)); StringWriter writer = new StringWriter(); - int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + int exitCode = JLINK_TOOL.run(pw, pw, args); return new Result(exitCode, writer.toString(), output); } @@ -699,7 +709,8 @@ public class JImageGenerator { String[] args = optionsPostProcessJLink(); System.err.println("jlink options: " + optionsPrettyPrint(args)); StringWriter writer = new StringWriter(); - int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + int exitCode = JLINK_TOOL.run(pw, pw, args); return new Result(exitCode, writer.toString(), output); } } diff --git a/langtools/.hgtags b/langtools/.hgtags index a116158f8b1..ab7c768cb4e 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -382,3 +382,5 @@ c8f02f0ecbd7cd6700f47416e4b7e9d5ec20ad77 jdk-9+136 dd56c243c199a540c9f1fbff4855f0934b32a9d0 jdk-9+137 90dd93e668a521642382561c47abe96ee2e065b7 jdk-9+138 17a82cb0e4b480e97021691d39917f15e3f7b653 jdk-9+139 +6842e63d6c3971172214b411f29965852ca175d1 jdk-9+140 +296c875051187918f8f3f87e9432036d13013d39 jdk-9+141 diff --git a/langtools/make/build.properties b/langtools/make/build.properties index c65ccb64bd1..4deb152a515 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -24,11 +24,12 @@ # #javac configuration for "normal build" (these will be passed to the bootstrap compiler): -javac.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options -Werror -g:source,lines,vars +javac.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options,-exports -Werror -g:source,lines,vars javac.source = 9 javac.target = 9 #version used to compile build tools +javac.build.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options -Werror -g:source,lines,vars javac.build.source = 8 javac.build.target = 8 diff --git a/langtools/make/build.xml b/langtools/make/build.xml index 3fec57e54ef..94a9aee474f 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -275,7 +275,7 @@ classpath="${ant.core.lib}" bootclasspath="${langtools.jdk.home}/jre/lib/rt.jar" includeantruntime="false"> - + - + - + diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java index 88079ff87c9..16185f28d85 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,7 +113,7 @@ public class Flags { * Internal compiler flags (no bits in the lower 16). *****************************************/ - /** Flag is set if symbol is deprecated. + /** Flag is set if symbol is deprecated. See also DEPRECATED_REMOVAL. */ public static final int DEPRECATED = 1<<17; @@ -293,6 +293,11 @@ public class Flags { */ public static final long SYSTEM_MODULE = 1L<<53; + /** + * Flag to indicate the given symbol has been deprecated and marked for removal. + */ + public static final long DEPRECATED_REMOVAL = 1L<<54; + /** Modifier masks. */ public static final int @@ -402,7 +407,8 @@ public class Flags { THROWS(Flags.THROWS), LAMBDA_METHOD(Flags.LAMBDA_METHOD), TYPE_TRANSLATED(Flags.TYPE_TRANSLATED), - MODULE(Flags.MODULE); + MODULE(Flags.MODULE), + DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL); Flag(long flag) { this.value = flag; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java index ddd61d65615..80ff1d24e9e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java @@ -25,11 +25,13 @@ package com.sun.tools.javac.code; +import java.util.Arrays; import java.util.EnumSet; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.main.Option; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Options; @@ -81,12 +83,13 @@ public class Lint } /** - * Returns a new Lint that has the given LintCategory suppressed. + * Returns a new Lint that has the given LintCategorys suppressed. + * @param lc one or more categories to be suppressed */ - public Lint suppress(LintCategory lc) { + public Lint suppress(LintCategory... lc) { Lint l = new Lint(this); - l.values.remove(lc); - l.suppressedValues.add(lc); + l.values.removeAll(Arrays.asList(lc)); + l.suppressedValues.addAll(Arrays.asList(lc)); return l; } @@ -100,10 +103,31 @@ public class Lint protected Lint(Context context) { // initialize values according to the lint options Options options = Options.instance(context); - values = EnumSet.noneOf(LintCategory.class); - for (Map.Entry e: map.entrySet()) { - if (options.lint(e.getKey())) - values.add(e.getValue()); + + if (options.isSet(Option.XLINT) || options.isSet(Option.XLINT_CUSTOM, "all")) { + // If -Xlint or -Xlint:all is given, enable all categories by default + values = EnumSet.allOf(LintCategory.class); + } else if (options.isSet(Option.XLINT_CUSTOM, "none")) { + // if -Xlint:none is given, disable all categories by default + values = EnumSet.noneOf(LintCategory.class); + } else { + // otherwise, enable on-by-default categories + values = EnumSet.noneOf(LintCategory.class); + + Source source = Source.instance(context); + if (source.compareTo(Source.JDK1_9) >= 0) { + values.add(LintCategory.DEP_ANN); + } + values.add(LintCategory.REMOVAL); + } + + // Look for specific overrides + for (LintCategory lc : LintCategory.values()) { + if (options.isSet(Option.XLINT_CUSTOM, lc.option)) { + values.add(lc); + } else if (options.isSet(Option.XLINT_CUSTOM, "-" + lc.option)) { + values.remove(lc); + } } suppressedValues = EnumSet.noneOf(LintCategory.class); @@ -212,6 +236,11 @@ public class Lint */ RAW("rawtypes"), + /** + * Warn about use of deprecated-for-removal items. + */ + REMOVAL("removal"), + /** * Warn about Serializable classes that do not provide a serial version ID. */ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 3eafa56303d..4c3ca382572 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -359,6 +359,10 @@ public abstract class Symbol extends AnnoConstruct implements Element { return (flags_field & DEPRECATED) != 0; } + public boolean isDeprecatedForRemoval() { + return (flags_field & DEPRECATED_REMOVAL) != 0; + } + public boolean isDeprecatableViaAnnotation() { switch (getKind()) { case LOCAL_VARIABLE: @@ -949,6 +953,7 @@ public abstract class Symbol extends AnnoConstruct implements Element { @Override @DefinedBy(Api.LANGUAGE_MODEL) public java.util.List getDirectives() { + complete(); completeUsesProvides(); return Collections.unmodifiableList(directives); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index d8f6cf527af..cd729736f88 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -30,6 +30,7 @@ import java.util.HashSet; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.WeakHashMap; import java.util.function.BiPredicate; @@ -468,89 +469,14 @@ public class Types { * and return-type substitutable with each method in the original list. */ private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List methodSyms) { - //pick argument types - simply take the signature that is a - //subsignature of all other signatures in the list (as per JLS 8.4.2) - List mostSpecific = List.nil(); - outer: for (Symbol msym1 : methodSyms) { - Type mt1 = memberType(origin.type, msym1); - for (Symbol msym2 : methodSyms) { - Type mt2 = memberType(origin.type, msym2); - if (!isSubSignature(mt1, mt2)) { - continue outer; - } - } - mostSpecific = mostSpecific.prepend(msym1); - } - if (mostSpecific.isEmpty()) { - return null; - } - - - //pick return types - this is done in two phases: (i) first, the most - //specific return type is chosen using strict subtyping; if this fails, - //a second attempt is made using return type substitutability (see JLS 8.4.5) - boolean phase2 = false; - Symbol bestSoFar = null; - while (bestSoFar == null) { - outer: for (Symbol msym1 : mostSpecific) { - Type mt1 = memberType(origin.type, msym1); - for (Symbol msym2 : methodSyms) { - Type mt2 = memberType(origin.type, msym2); - if (phase2 ? - !returnTypeSubstitutable(mt1, mt2) : - !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) { - continue outer; + return mergeAbstracts(methodSyms, origin.type, false) + .map(bestSoFar -> new FunctionDescriptor(bestSoFar.baseSymbol()) { + @Override + public Type getType(Type origin) { + Type mt = memberType(origin, getSymbol()); + return createMethodTypeWithThrown(mt, bestSoFar.type.getThrownTypes()); } - } - bestSoFar = msym1; - } - if (phase2) { - break; - } else { - phase2 = true; - } - } - if (bestSoFar == null) return null; - - //merge thrown types - form the intersection of all the thrown types in - //all the signatures in the list - List thrown = null; - Type mt1 = memberType(origin.type, bestSoFar); - boolean toErase = !mt1.hasTag(FORALL); - for (Symbol msym2 : methodSyms) { - Type mt2 = memberType(origin.type, msym2); - List thrown_mt2 = mt2.getThrownTypes(); - if (toErase) { - thrown_mt2 = erasure(thrown_mt2); - } else { - /* If bestSoFar is generic then all the methods are generic. - * The opposite is not true: a non generic method can override - * a generic method (raw override) so it's safe to cast mt1 and - * mt2 to ForAll. - */ - ForAll fa1 = (ForAll)mt1; - ForAll fa2 = (ForAll)mt2; - thrown_mt2 = subst(thrown_mt2, fa2.tvars, fa1.tvars); - } - thrown = (thrown == null) ? - thrown_mt2 : - chk.intersect(thrown_mt2, thrown); - } - - final List thrown1 = thrown; - return new FunctionDescriptor(bestSoFar) { - @Override - public Type getType(Type origin) { - Type mt = memberType(origin, getSymbol()); - return createMethodTypeWithThrown(mt, thrown1); - } - }; - } - - boolean isSubtypeInternal(Type s, Type t) { - return (s.isPrimitive() && t.isPrimitive()) ? - isSameType(t, s) : - isSubtype(s, t); + }).orElse(null); } FunctionDescriptorLookupError failure(String msg, Object... args) { @@ -2604,6 +2530,106 @@ public class Types { return false; } + /** + * This enum defines the strategy for implementing most specific return type check + * during the most specific and functional interface checks. + */ + public enum MostSpecificReturnCheck { + /** + * Return r1 is more specific than r2 if {@code r1 <: r2}. Extra care required for (i) handling + * method type variables (if either method is generic) and (ii) subtyping should be replaced + * by type-equivalence for primitives. This is essentially an inlined version of + * {@link Types#resultSubtype(Type, Type, Warner)}, where the assignability check has been + * replaced with a strict subtyping check. + */ + BASIC() { + @Override + public boolean test(Type mt1, Type mt2, Types types) { + List tvars = mt1.getTypeArguments(); + List svars = mt2.getTypeArguments(); + Type t = mt1.getReturnType(); + Type s = types.subst(mt2.getReturnType(), svars, tvars); + return types.isSameType(t, s) || + !t.isPrimitive() && + !s.isPrimitive() && + types.isSubtype(t, s); + } + }, + /** + * Return r1 is more specific than r2 if r1 is return-type-substitutable for r2. + */ + RTS() { + @Override + public boolean test(Type mt1, Type mt2, Types types) { + return types.returnTypeSubstitutable(mt1, mt2); + } + }; + + public abstract boolean test(Type mt1, Type mt2, Types types); + } + + /** + * Merge multiple abstract methods. The preferred method is a method that is a subsignature + * of all the other signatures and whose return type is more specific {@see MostSpecificReturnCheck}. + * The resulting preferred method has a thrown clause that is the intersection of the merged + * methods' clauses. + */ + public Optional mergeAbstracts(List ambiguousInOrder, Type site, boolean sigCheck) { + //first check for preconditions + boolean shouldErase = false; + List erasedParams = ambiguousInOrder.head.erasure(this).getParameterTypes(); + for (Symbol s : ambiguousInOrder) { + if ((s.flags() & ABSTRACT) == 0 || + (sigCheck && !isSameTypes(erasedParams, s.erasure(this).getParameterTypes()))) { + return Optional.empty(); + } else if (s.type.hasTag(FORALL)) { + shouldErase = true; + } + } + //then merge abstracts + for (MostSpecificReturnCheck mostSpecificReturnCheck : MostSpecificReturnCheck.values()) { + outer: for (Symbol s : ambiguousInOrder) { + Type mt = memberType(site, s); + List allThrown = mt.getThrownTypes(); + for (Symbol s2 : ambiguousInOrder) { + if (s != s2) { + Type mt2 = memberType(site, s2); + if (!isSubSignature(mt, mt2) || + !mostSpecificReturnCheck.test(mt, mt2, this)) { + //ambiguity cannot be resolved + continue outer; + } else { + List thrownTypes2 = mt2.getThrownTypes(); + if (!mt.hasTag(FORALL) && shouldErase) { + thrownTypes2 = erasure(thrownTypes2); + } else if (mt.hasTag(FORALL)) { + //subsignature implies that if most specific is generic, then all other + //methods are too + Assert.check(mt2.hasTag(FORALL)); + // if both are generic methods, adjust thrown types ahead of intersection computation + thrownTypes2 = subst(thrownTypes2, mt2.getTypeArguments(), mt.getTypeArguments()); + } + allThrown = chk.intersect(allThrown, thrownTypes2); + } + } + } + return (allThrown == mt.getThrownTypes()) ? + Optional.of(s) : + Optional.of(new MethodSymbol( + s.flags(), + s.name, + createMethodTypeWithThrown(s.type, allThrown), + s.owner) { + @Override + public Symbol baseSymbol() { + return s; + } + }); + } + } + return Optional.empty(); + } + // class ImplementationCache { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java index bf43a6e5ad4..574ae1008a6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -340,6 +340,13 @@ public class Annotate { && toAnnotate.owner.kind != MTH && types.isSameType(c.type, syms.deprecatedType)) { toAnnotate.flags_field |= Flags.DEPRECATED; + Attribute fr = c.member(names.forRemoval); + if (fr instanceof Attribute.Constant) { + Attribute.Constant v = (Attribute.Constant) fr; + if (v.type == syms.booleanType && ((Integer) v.value) != 0) { + toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL; + } + } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 2743702d11d..3aee3c44504 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2398,6 +2398,7 @@ public class Attr extends JCTree.Visitor { try { if (needsRecovery && isSerializable(pt())) { localEnv.info.isSerializable = true; + localEnv.info.isLambda = true; } List explicitParamTypes = null; if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { @@ -2969,7 +2970,7 @@ public class Attr extends JCTree.Visitor { } if (isTargetSerializable) { - chk.checkElemAccessFromSerializableLambda(that); + chk.checkAccessFromSerializableElement(that, true); } } @@ -3364,7 +3365,7 @@ public class Attr extends JCTree.Visitor { } if (env.info.isSerializable) { - chk.checkElemAccessFromSerializableLambda(tree); + chk.checkAccessFromSerializableElement(tree, env.info.isLambda); } result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo); @@ -3507,7 +3508,7 @@ public class Attr extends JCTree.Visitor { } if (env.info.isSerializable) { - chk.checkElemAccessFromSerializableLambda(tree); + chk.checkAccessFromSerializableElement(tree, env.info.isLambda); } env.info.selectSuper = selectSuperPrev; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java index 368efd19db1..573e8948136 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,10 +56,15 @@ public class AttrContext { */ boolean selectSuper = false; - /** Is the current target of lambda expression or method reference serializable? + /** Is the current target of lambda expression or method reference serializable or is this a + * serializable class? */ boolean isSerializable = false; + /** Is this a lambda environment? + */ + boolean isLambda = false; + /** Is this a speculative attribution environment? */ boolean isSpeculative = false; @@ -117,6 +122,7 @@ public class AttrContext { info.returnResult = returnResult; info.defaultSuperCallSite = defaultSuperCallSite; info.isSerializable = isSerializable; + info.isLambda = isLambda; info.isSpeculative = isSpeculative; info.isAnonymousDiamond = isAnonymousDiamond; info.isNewClass = isNewClass; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 1a774450eac..bc1ab5f5e06 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -87,7 +87,7 @@ public class Check { private final JavaFileManager fileManager; private final Source source; private final Profile profile; - private final boolean warnOnAccessToSensitiveMembers; + private final boolean warnOnAnyAccessToMembers; // The set of lint options currently in effect. It is initialized // from the context, and then is set/reset as needed by Attr as it @@ -131,7 +131,7 @@ public class Check { allowStrictMethodClashCheck = source.allowStrictMethodClashCheck(); allowPrivateSafeVarargs = source.allowPrivateSafeVarargs(); allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation(); - warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers"); + warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers"); Target target = Target.instance(context); syntheticNameChar = target.syntheticNameChar(); @@ -139,11 +139,14 @@ public class Check { profile = Profile.instance(context); boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); + boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL); boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); boolean enforceMandatoryWarnings = true; deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated, enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION); + removalHandler = new MandatoryWarningHandler(log, verboseRemoval, + enforceMandatoryWarnings, "removal", LintCategory.REMOVAL); uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED); sunApiHandler = new MandatoryWarningHandler(log, false, @@ -185,6 +188,10 @@ public class Check { */ private MandatoryWarningHandler deprecationHandler; + /** A handler for messages about deprecated-for-removal usage. + */ + private MandatoryWarningHandler removalHandler; + /** A handler for messages about unchecked or unsafe usage. */ private MandatoryWarningHandler uncheckedHandler; @@ -218,8 +225,13 @@ public class Check { * @param sym The deprecated symbol. */ void warnDeprecated(DiagnosticPosition pos, Symbol sym) { - if (!lint.isSuppressed(LintCategory.DEPRECATION)) + if (sym.isDeprecatedForRemoval()) { + if (!lint.isSuppressed(LintCategory.REMOVAL)) { + removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location()); + } + } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) { deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); + } } /** Warn about unchecked operation. @@ -257,6 +269,7 @@ public class Check { */ public void reportDeferredDiagnostics() { deprecationHandler.reportDeferredDiagnostic(); + removalHandler.reportDeferredDiagnostic(); uncheckedHandler.reportDeferredDiagnostic(); sunApiHandler.reportDeferredDiagnostic(); } @@ -2605,8 +2618,11 @@ public class Check { } } - void checkElemAccessFromSerializableLambda(final JCTree tree) { - if (warnOnAccessToSensitiveMembers) { + void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) { + if (warnOnAnyAccessToMembers || + (lint.isEnabled(LintCategory.SERIAL) && + !lint.isSuppressed(LintCategory.SERIAL) && + isLambda)) { Symbol sym = TreeInfo.symbol(tree); if (!sym.kind.matches(KindSelector.VAL_MTH)) { return; @@ -2622,9 +2638,16 @@ public class Check { } if (!types.isSubtype(sym.owner.type, syms.serializableType) && - isEffectivelyNonPublic(sym)) { - log.warning(tree.pos(), - "access.to.sensitive.member.from.serializable.element", sym); + isEffectivelyNonPublic(sym)) { + if (isLambda) { + if (belongsToRestrictedPackage(sym)) { + log.warning(LintCategory.SERIAL, tree.pos(), + "access.to.member.from.serializable.lambda", sym); + } + } else { + log.warning(tree.pos(), + "access.to.member.from.serializable.element", sym); + } } } } @@ -2643,6 +2666,14 @@ public class Check { return false; } + private boolean belongsToRestrictedPackage(Symbol sym) { + String fullName = sym.packge().fullname.toString(); + return fullName.startsWith("java.") || + fullName.startsWith("javax.") || + fullName.startsWith("sun.") || + fullName.contains(".internal."); + } + /** Report a conflict between a user symbol and a synthetic symbol. */ private void syntheticError(DiagnosticPosition pos, Symbol sym) { @@ -3212,9 +3243,9 @@ public class Check { } void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) { - if ((s.flags() & DEPRECATED) != 0 && - (other.flags() & DEPRECATED) == 0 && - s.outermostClass() != other.outermostClass()) { + if ( (s.isDeprecatedForRemoval() + || s.isDeprecated() && !other.isDeprecated()) + && s.outermostClass() != other.outermostClass()) { deferredLintHandler.report(new DeferredLintHandler.LintLogger() { @Override public void report() { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 1fa377635df..5eb09f5c978 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -29,6 +29,7 @@ package com.sun.tools.javac.comp; import java.util.HashMap; +import com.sun.source.tree.LambdaExpressionTree.BodyKind; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.tree.*; @@ -224,7 +225,7 @@ public class Flow { diagHandler = new Log.DiscardDiagnosticHandler(log); } try { - new AliveAnalyzer().analyzeTree(env, that, make); + new LambdaAliveAnalyzer().analyzeTree(env, that, make); } finally { if (!speculative) { log.popDiagnosticHandler(diagHandler); @@ -241,19 +242,7 @@ public class Flow { //related errors, which will allow for more errors to be detected Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); try { - new AssignAnalyzer() { - WriteableScope enclosedSymbols = WriteableScope.create(env.enclClass.sym); - @Override - public void visitVarDef(JCVariableDecl tree) { - enclosedSymbols.enter(tree.sym); - super.visitVarDef(tree); - } - @Override - protected boolean trackable(VarSymbol sym) { - return enclosedSymbols.includes(sym) && - sym.owner.kind == MTH; - } - }.analyzeTree(env, that); + new LambdaAssignAnalyzer(env).analyzeTree(env, that); LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); flowAnalyzer.analyzeTree(env, that, make); return flowAnalyzer.inferredThrownTypes; @@ -1340,6 +1329,79 @@ public class Flow { } } + /** + * Specialized pass that performs reachability analysis on a lambda + */ + class LambdaAliveAnalyzer extends AliveAnalyzer { + + boolean inLambda; + + @Override + public void visitReturn(JCReturn tree) { + //ignore lambda return expression (which might not even be attributed) + recordExit(new PendingExit(tree)); + } + + @Override + public void visitLambda(JCLambda tree) { + if (inLambda || tree.getBodyKind() == BodyKind.EXPRESSION) { + return; + } + inLambda = true; + try { + super.visitLambda(tree); + } finally { + inLambda = false; + } + } + + @Override + public void visitClassDef(JCClassDecl tree) { + //skip + } + } + + /** + * Specialized pass that performs DA/DU on a lambda + */ + class LambdaAssignAnalyzer extends AssignAnalyzer { + WriteableScope enclosedSymbols; + boolean inLambda; + + LambdaAssignAnalyzer(Env env) { + enclosedSymbols = WriteableScope.create(env.enclClass.sym); + } + + @Override + public void visitLambda(JCLambda tree) { + if (inLambda) { + return; + } + inLambda = true; + try { + super.visitLambda(tree); + } finally { + inLambda = false; + } + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + enclosedSymbols.enter(tree.sym); + super.visitVarDef(tree); + } + @Override + protected boolean trackable(VarSymbol sym) { + return enclosedSymbols.includes(sym) && + sym.owner.kind == MTH; + } + + @Override + public void visitClassDef(JCClassDecl tree) { + //skip + } + } + /** * Specialized pass that performs inference of thrown types for lambdas. */ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index bf919e862ab..49f8489193f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1691,28 +1691,6 @@ public class Resolve { } } //where - Type mostSpecificReturnType(Type mt1, Type mt2) { - Type rt1 = mt1.getReturnType(); - Type rt2 = mt2.getReturnType(); - - if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL)) { - //if both are generic methods, adjust return type ahead of subtyping check - rt1 = types.subst(rt1, mt1.getTypeArguments(), mt2.getTypeArguments()); - } - //first use subtyping, then return type substitutability - if (types.isSubtype(rt1, rt2)) { - return mt1; - } else if (types.isSubtype(rt2, rt1)) { - return mt2; - } else if (types.returnTypeSubstitutable(mt1, mt2)) { - return mt1; - } else if (types.returnTypeSubstitutable(mt2, mt1)) { - return mt2; - } else { - return null; - } - } - //where Symbol ambiguityError(Symbol m1, Symbol m2) { if (((m1.flags() | m2.flags()) & CLASH) != 0) { return (m1.flags() & CLASH) == 0 ? m1 : m2; @@ -4112,43 +4090,7 @@ public class Resolve { */ Symbol mergeAbstracts(Type site) { List ambiguousInOrder = ambiguousSyms.reverse(); - for (Symbol s : ambiguousInOrder) { - Type mt = types.memberType(site, s); - boolean found = true; - List allThrown = mt.getThrownTypes(); - for (Symbol s2 : ambiguousInOrder) { - Type mt2 = types.memberType(site, s2); - if ((s2.flags() & ABSTRACT) == 0 || - !types.overrideEquivalent(mt, mt2) || - !types.isSameTypes(s.erasure(types).getParameterTypes(), - s2.erasure(types).getParameterTypes())) { - //ambiguity cannot be resolved - return this; - } - Type mst = mostSpecificReturnType(mt, mt2); - if (mst == null || mst != mt) { - found = false; - break; - } - List thrownTypes2 = mt2.getThrownTypes(); - if (mt.hasTag(FORALL) && mt2.hasTag(FORALL)) { - // if both are generic methods, adjust thrown types ahead of intersection computation - thrownTypes2 = types.subst(thrownTypes2, mt2.getTypeArguments(), mt.getTypeArguments()); - } - allThrown = chk.intersect(allThrown, thrownTypes2); - } - if (found) { - //all ambiguous methods were abstract and one method had - //most specific return type then others - return (allThrown == mt.getThrownTypes()) ? - s : new MethodSymbol( - s.flags(), - s.name, - types.createMethodTypeWithThrown(s.type, allThrown), - s.owner); - } - } - return this; + return types.mergeAbstracts(ambiguousInOrder, site, true).orElse(this); } @Override diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index 7b9f740c1aa..c941de3f5b7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,7 +103,6 @@ public class TypeEnter implements Completer { private final TypeAnnotations typeAnnotations; private final Types types; private final JCDiagnostic.Factory diags; - private final Source source; private final DeferredLintHandler deferredLintHandler; private final Lint lint; private final TypeEnvs typeEnvs; @@ -131,7 +130,6 @@ public class TypeEnter implements Completer { typeAnnotations = TypeAnnotations.instance(context); types = Types.instance(context); diags = JCDiagnostic.Factory.instance(context); - source = Source.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); lint = Lint.instance(context); typeEnvs = TypeEnvs.instance(context); @@ -178,6 +176,7 @@ public class TypeEnter implements Completer { /** Complete entering a class. * @param sym The symbol of the class to be completed. */ + @Override public void complete(Symbol sym) throws CompletionFailure { // Suppress some (recursive) MemberEnter invocations if (!completionEnabled) { @@ -414,7 +413,7 @@ public class TypeEnter implements Completer { Type attribImportType(JCTree tree, Env env) { Assert.check(completionEnabled); Lint prevLint = chk.setLint(allowDeprecationOnImport ? - lint : lint.suppress(LintCategory.DEPRECATION)); + lint : lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL)); try { // To prevent deep recursion, suppress completion of some // types. @@ -751,12 +750,12 @@ public class TypeEnter implements Completer { // can attribute the annotation types and then check to see if the // @Deprecated annotation is present. attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); - if (hasDeprecatedAnnotation(tree.mods.annotations)) - sym.flags_field |= DEPRECATED; + handleDeprecatedAnnotation(tree.mods.annotations, sym); chk.checkNonCyclicDecl(tree); } //where: + @Override protected JCExpression clearTypeParams(JCExpression superType) { switch (superType.getTag()) { case TYPEAPPLY: @@ -767,16 +766,29 @@ public class TypeEnter implements Completer { } /** - * Check if a list of annotations contains a reference to - * java.lang.Deprecated. + * If a list of annotations contains a reference to java.lang.Deprecated, + * set the DEPRECATED flag. + * If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL. **/ - private boolean hasDeprecatedAnnotation(List annotations) { + private void handleDeprecatedAnnotation(List annotations, Symbol sym) { for (List al = annotations; !al.isEmpty(); al = al.tail) { JCAnnotation a = al.head; - if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty()) - return true; + if (a.annotationType.type == syms.deprecatedType) { + sym.flags_field |= Flags.DEPRECATED; + a.args.stream() + .filter(e -> e.hasTag(ASSIGN)) + .map(e -> (JCAssign) e) + .filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval) + .findFirst() + .ifPresent(assign -> { + JCExpression rhs = TreeInfo.skipParens(assign.rhs); + if (rhs.hasTag(LITERAL) + && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) { + sym.flags_field |= DEPRECATED_REMOVAL; + } + }); + } } - return false; } @Override diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java index c4e0780cbf1..a779836f06d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java @@ -52,8 +52,6 @@ import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; -import com.sun.tools.javac.code.Lint; -import com.sun.tools.javac.code.Source; import com.sun.tools.javac.main.Option; import com.sun.tools.javac.main.OptionHelper; import com.sun.tools.javac.main.OptionHelper.GrumpyHelper; @@ -85,7 +83,10 @@ public abstract class BaseFileManager implements JavaFileManager { log = Log.instance(context); options = Options.instance(context); classLoaderClass = options.get("procloader"); - locations.update(log, Lint.instance(context), FSInfo.instance(context)); + + // Avoid initializing Lint + boolean warn = options.isLintSet("path"); + locations.update(log, warn, FSInfo.instance(context)); // Setting this option is an indication that close() should defer actually closing // the file manager until after a specified period of inactivity. @@ -171,14 +172,6 @@ public abstract class BaseFileManager implements JavaFileManager { private long lastUsedTime = System.currentTimeMillis(); protected long deferredCloseTimeout = 0; - protected Source getSource() { - String sourceName = options.get(Option.SOURCE); - Source source = null; - if (sourceName != null) - source = Source.lookup(sourceName); - return (source != null ? source : Source.DEFAULT); - } - protected ClassLoader getClassLoader(URL[] urls) { ClassLoader thisClassLoader = getClass().getClassLoader(); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java index 4e32325ef11..3e41246db81 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java @@ -42,7 +42,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.ProviderNotFoundException; -import java.nio.file.spi.FileSystemProvider; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -63,7 +62,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.zip.ZipFile; import javax.lang.model.SourceVersion; import javax.tools.JavaFileManager; @@ -159,10 +157,9 @@ public class Locations { } } - // could replace Lint by "boolean warn" - void update(Log log, Lint lint, FSInfo fsInfo) { + void update(Log log, boolean warn, FSInfo fsInfo) { this.log = log; - warn = lint.isEnabled(Lint.LintCategory.PATH); + this.warn = warn; this.fsInfo = fsInfo; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 7d7b4c3ead0..662bedc71d8 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1460,7 +1460,6 @@ public class ClassReader { ListBuffer proxies = new ListBuffer<>(); for (int i = 0; i v : proxy.values) { + if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) { + Attribute.Constant c = (Attribute.Constant) v.snd; + if (c.type == syms.booleanType && ((Integer) c.value) != 0) { + sym.flags_field |= DEPRECATED_REMOVAL; + } + } + } } proxies.append(proxy); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index a869718d6b3..d64b6356280 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -37,6 +37,7 @@ import java.util.Comparator; import java.util.EnumSet; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.ServiceLoader; @@ -111,7 +112,6 @@ public enum Option { "all", log.localize(PrefixKind.JAVAC, "opt.Xlint.all"))); for (LintCategory lc : LintCategory.values()) { - if (lc.hidden) continue; log.printRawLines(WriterKind.STDOUT, String.format(LINT_KEY_FORMAT, lc.option, @@ -801,8 +801,8 @@ public enum Option { /** The kind of choices for this option, if any. */ private final ChoiceKind choiceKind; - /** The choices for this option, if any, and whether or not the choices are hidden. */ - private final Map choices; + /** The choices for this option, if any. */ + private final Set choices; /** * Looks up the first option matching the given argument in the full set of options. @@ -815,7 +815,8 @@ public enum Option { /** * Looks up the first option matching the given argument within a set of options. - * @param arg the argument to be matches + * @param arg the argument to be matched + * @param options the set of possible options * @return the first option that matches, or null if none. */ public static Option lookup(String arg, Set

+ * The {@code read} method of the {@code InputStream} may throw the {@link InterruptedIOException} + * to signal the user canceled the input. The currently running snippet will be automatically + * {@link JShell#stop() stopped}. + *

* The default, if this is not set, is to provide an empty input stream * -- {@code new ByteArrayInputStream(new byte[0])}. * @@ -428,7 +433,12 @@ public class JShell implements AutoCloseable { } /** - * Remove a declaration from the state. + * Remove a declaration from the state. That is, if the snippet is an + * {@linkplain jdk.jshell.Snippet.Status#isActive() active} + * {@linkplain jdk.jshell.PersistentSnippet persistent} snippet, remove the + * snippet and update the JShell evaluation state accordingly. + * For all active snippets, change the {@linkplain #status status} to + * {@link jdk.jshell.Snippet.Status#DROPPED DROPPED}. * @param snippet The snippet to remove * @return The list of events from updating declarations dependent on the * dropped snippet. @@ -436,7 +446,7 @@ public class JShell implements AutoCloseable { * @throws IllegalArgumentException if the snippet is not associated with * this {@code JShell} instance. */ - public List drop(PersistentSnippet snippet) throws IllegalStateException { + public List drop(Snippet snippet) throws IllegalStateException { checkIfAlive(); checkValidSnippet(snippet); List events = eval.drop(snippet); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Key.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Key.java index 5779493a91c..eb837a17f75 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Key.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Key.java @@ -74,7 +74,7 @@ abstract class Key { /** * Grouping for snippets which persist and influence future code. * They are keyed off at least the name. They may be Modified/Replaced - * with new input and can be dropped (JShell#drop). + * with new input. */ static abstract class PersistentKey extends Key { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/PersistentSnippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/PersistentSnippet.java index 985c8332b3d..b615c78e1dc 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/PersistentSnippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/PersistentSnippet.java @@ -28,8 +28,8 @@ package jdk.jshell; /** * Grouping for Snippets which persist and influence future code. * A persistent snippet can be - * {@linkplain jdk.jshell.Snippet.Status#OVERWRITTEN overwritten)} - * with new input and can be dropped {@link JShell#drop}. + * {@linkplain jdk.jshell.Snippet.Status#OVERWRITTEN overwritten} + * with new input. *

* PersistentSnippet is immutable: an access to * any of its methods will always return the same result. diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java index 955f8366755..3268dd61a02 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java @@ -443,9 +443,7 @@ public abstract class Snippet { /** * The snippet is inactive because of an explicit call to - * the {@link JShell#drop(PersistentSnippet)}. - * Only a {@link jdk.jshell.PersistentSnippet} can have this - * {@code Status}. + * the {@link JShell#drop(Snippet)}. *

* The snippet is not visible to other snippets * ({@link Status#isDefined() isDefined() == false}) @@ -525,10 +523,11 @@ public abstract class Snippet { /** * Indicates whether the Snippet is active, that is, - * will the snippet be re-evaluated when a new + * will a {@linkplain jdk.jshell.PersistentSnippet persistent} + * snippet be re-evaluated when a new * {@link JShell#eval(java.lang.String) JShell.eval(String)} or - * {@link JShell#drop(jdk.jshell.PersistentSnippet) - * JShell.drop(PersistentSnippet)} that could change + * {@link JShell#drop(jdk.jshell.Snippet) + * JShell.drop(Snippet)} that could change * its status is invoked. This is more broad than * {@link Status#isDefined()} since a Snippet which is * {@link Status#RECOVERABLE_NOT_DEFINED} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java index 47bb1b117f8..683038bbb26 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java @@ -30,7 +30,7 @@ import jdk.jshell.Snippet.Status; /** * A description of a change to a Snippet. These are generated by direct changes * to state with {@link JShell#eval(java.lang.String) JShell.eval(String)} or - * {@link JShell#drop(jdk.jshell.PersistentSnippet) JShell.drop(PersistentSnippet)}, + * {@link JShell#drop(jdk.jshell.Snippet) JShell.drop(Snippet)}, * or indirectly by these same methods as * dependencies change or Snippets are overwritten. For direct changes, the * {@link SnippetEvent#causeSnippet()} is {@code null}. @@ -108,7 +108,7 @@ public class SnippetEvent { * creation of a new Snippet via * {@link jdk.jshell.JShell#eval(java.lang.String) eval} or it is the * explicit drop of a Snippet with - * {@link jdk.jshell.JShell#drop(jdk.jshell.PersistentSnippet) drop}. + * {@link jdk.jshell.JShell#drop(jdk.jshell.Snippet) drop}. * * @return the Snippet which caused this change or {@code null} if * directly caused by an API action. diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index 309f4b4ba09..ce7fd0eb31e 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -116,6 +116,7 @@ import javax.lang.model.SourceVersion; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.QualifiedNameable; +import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.ExecutableType; @@ -132,6 +133,7 @@ import javax.tools.ToolProvider; import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; import static java.util.stream.Collectors.joining; import static jdk.jshell.SourceCodeAnalysis.Completeness.DEFINITELY_INCOMPLETE; +import static jdk.jshell.TreeDissector.printType; /** * The concrete implementation of SourceCodeAnalysis. @@ -1185,7 +1187,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { proc.debug(ex, "SourceCodeAnalysisImpl.element2String(..., " + el + ")"); } - return Util.expunge(elementHeader(el)); + return Util.expunge(elementHeader(sourceCache.originalTask, el, !hasSyntheticParameterNames(el))); } private boolean hasSyntheticParameterNames(Element el) { @@ -1248,7 +1250,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { topLevelName2Signature2Method.put(binaryName, cache = createMethodCache(binaryName)); } - String handle = elementHeader(method, false); + String handle = elementHeader(originalTask, method, false); return cache.getOrDefault(handle, method); } @@ -1276,7 +1278,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { Element currentMethod = trees.getElement(getCurrentPath()); if (currentMethod != null) { - signature2Method.put(elementHeader(currentMethod, false), currentMethod); + signature2Method.put(elementHeader(originalTask, currentMethod, false), currentMethod); } return null; @@ -1331,39 +1333,79 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { return availableSources = result; } - private String elementHeader(Element el) { - return elementHeader(el, true); + private String elementHeader(AnalyzeTask at, Element el) { + return elementHeader(at, el, true); } - private String elementHeader(Element el, boolean includeParameterNames) { + private String elementHeader(AnalyzeTask at, Element el, boolean includeParameterNames) { switch (el.getKind()) { - case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE: - return ((TypeElement) el).getQualifiedName().toString(); + case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE: { + TypeElement type = (TypeElement)el; + String fullname = type.getQualifiedName().toString(); + Element pkg = at.getElements().getPackageOf(el); + String name = pkg == null ? fullname : + proc.maps.fullClassNameAndPackageToClass(fullname, ((PackageElement)pkg).getQualifiedName().toString()); + + return name + typeParametersOpt(at, type.getTypeParameters()); + } + case TYPE_PARAMETER: { + TypeParameterElement tp = (TypeParameterElement)el; + String name = tp.getSimpleName().toString(); + + List bounds = tp.getBounds(); + boolean boundIsObject = bounds.isEmpty() || + bounds.size() == 1 && at.getTypes().isSameType(bounds.get(0), Symtab.instance(at.getContext()).objectType); + + return boundIsObject + ? name + : name + " extends " + bounds.stream() + .map(bound -> printType(at, proc, bound)) + .collect(joining(" & ")); + } case FIELD: - return elementHeader(el.getEnclosingElement()) + "." + el.getSimpleName() + ":" + el.asType(); + return elementHeader(at, el.getEnclosingElement()) + "." + el.getSimpleName() + ":" + el.asType(); case ENUM_CONSTANT: - return elementHeader(el.getEnclosingElement()) + "." + el.getSimpleName(); + return elementHeader(at, el.getEnclosingElement()) + "." + el.getSimpleName(); case EXCEPTION_PARAMETER: case LOCAL_VARIABLE: case PARAMETER: case RESOURCE_VARIABLE: return el.getSimpleName() + ":" + el.asType(); - case CONSTRUCTOR: case METHOD: + case CONSTRUCTOR: case METHOD: { StringBuilder header = new StringBuilder(); - header.append(elementHeader(el.getEnclosingElement())); - if (el.getKind() == ElementKind.METHOD) { - header.append("."); - header.append(el.getSimpleName()); + + boolean isMethod = el.getKind() == ElementKind.METHOD; + ExecutableElement method = (ExecutableElement) el; + + if (isMethod) { + // return type + header.append(printType(at, proc, method.getReturnType())).append(" "); + } else { + // type parameters for the constructor + String typeParameters = typeParametersOpt(at, method.getTypeParameters()); + if (!typeParameters.isEmpty()) { + header.append(typeParameters).append(" "); + } } + + // receiver type + String clazz = elementHeader(at, el.getEnclosingElement()); + header.append(clazz); + + if (isMethod) { + //method name with type parameters + (clazz.isEmpty() ? header : header.append(".")) + .append(typeParametersOpt(at, method.getTypeParameters())) + .append(el.getSimpleName()); + } + + // arguments header.append("("); String sep = ""; - ExecutableElement method = (ExecutableElement) el; for (Iterator i = method.getParameters().iterator(); i.hasNext();) { VariableElement p = i.next(); header.append(sep); if (!i.hasNext() && method.isVarArgs()) { - header.append(unwrapArrayType(p.asType())); - header.append("..."); - + header.append(printType(at, proc, unwrapArrayType(p.asType()))).append("..."); } else { - header.append(p.asType()); + header.append(printType(at, proc, p.asType())); } if (includeParameterNames) { header.append(" "); @@ -1372,8 +1414,18 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { sep = ", "; } header.append(")"); + + // throws + List thrownTypes = method.getThrownTypes(); + if (!thrownTypes.isEmpty()) { + header.append(" throws ") + .append(thrownTypes.stream() + .map(type -> printType(at, proc, type)) + .collect(joining(", "))); + } return header.toString(); - default: + } + default: return el.toString(); } } @@ -1383,6 +1435,12 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { } return arrayType; } + private String typeParametersOpt(AnalyzeTask at, List typeParameters) { + return typeParameters.isEmpty() ? "" + : typeParameters.stream() + .map(tp -> elementHeader(at, tp)) + .collect(joining(", ", "<", ">")); + } @Override public String analyzeType(String code, int cursor) { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java index 1b582fa9b10..c0553305119 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java @@ -42,7 +42,7 @@ class PipeInputStream extends InputStream { @Override public synchronized int read() throws IOException { - if (start == end) { + if (start == end && !closed) { inputNeeded(); } while (start == end) { @@ -62,6 +62,32 @@ class PipeInputStream extends InputStream { } } + @Override + public synchronized int read(byte[] b, int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + int c = read(); + if (c == -1) { + return -1; + } + b[off] = (byte)c; + + int totalRead = 1; + while (totalRead < len && start != end) { + int r = read(); + if (r == (-1)) + break; + b[off + totalRead++] = (byte) r; + } + return totalRead; + } + protected void inputNeeded() throws IOException {} private synchronized void write(int b) { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java index da8decab065..3ea2975ca56 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java @@ -28,6 +28,7 @@ import jdk.jshell.spi.ExecutionEnv; import java.io.IOException; import java.io.InputStream; +import java.io.InterruptedIOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; @@ -42,6 +43,7 @@ import java.util.function.Consumer; import com.sun.jdi.VirtualMachine; import jdk.jshell.spi.ExecutionControl; +import jdk.jshell.spi.ExecutionControl.ExecutionControlException; /** @@ -54,6 +56,10 @@ import jdk.jshell.spi.ExecutionControl; */ public class Util { + private static final int TAG_DATA = 0; + private static final int TAG_CLOSED = 1; + private static final int TAG_EXCEPTION = 2; + // never instanciated private Util() {} @@ -131,6 +137,25 @@ public class Util { inputSignal.write('1'); inputSignal.flush(); } + @Override + public synchronized int read() throws IOException { + int tag = super.read(); + switch (tag) { + case TAG_DATA: return super.read(); + case TAG_CLOSED: close(); return -1; + case TAG_EXCEPTION: + int len = (super.read() << 0) + (super.read() << 8) + (super.read() << 16) + (super.read() << 24); + byte[] message = new byte[len]; + for (int i = 0; i < len; i++) { + message[i] = (byte) super.read(); + } + throw new IOException(new String(message, "UTF-8")); + case -1: + return -1; + default: + throw new IOException("Internal error: unrecognized message tag: " + tag); + } + } }; inputs.put(e.getKey(), inputPipe.createOutput()); e.getValue().accept(inputPipe); @@ -163,6 +188,7 @@ public class Util { public static ExecutionControl remoteInputOutput(InputStream input, OutputStream output, Map outputStreamMap, Map inputStreamMap, BiFunction factory) throws IOException { + ExecutionControl[] result = new ExecutionControl[1]; Map augmentedStreamMap = new HashMap<>(outputStreamMap); ObjectOutput commandOut = new ObjectOutputStream(Util.multiplexingOutputStream("$command", output)); for (Entry e : inputStreamMap.entrySet()) { @@ -172,7 +198,28 @@ public class Util { @Override public void write(int b) throws IOException { //value ignored, just a trigger to read from the input - inTarget.write(in.read()); + try { + int r = in.read(); + if (r == (-1)) { + inTarget.write(TAG_CLOSED); + } else { + inTarget.write(new byte[] {TAG_DATA, (byte) r}); + } + } catch (InterruptedIOException exc) { + try { + result[0].stop(); + } catch (ExecutionControlException ex) { + debug(ex, "$" + e.getKey() + "-input-requested.write"); + } + } catch (IOException exc) { + byte[] message = exc.getMessage().getBytes("UTF-8"); + inTarget.write(TAG_EXCEPTION); + inTarget.write((message.length >> 0) & 0xFF); + inTarget.write((message.length >> 8) & 0xFF); + inTarget.write((message.length >> 16) & 0xFF); + inTarget.write((message.length >> 24) & 0xFF); + inTarget.write(message); + } } }); } @@ -180,7 +227,7 @@ public class Util { OutputStream commandInTarget = commandIn.createOutput(); augmentedStreamMap.put("$command", commandInTarget); new DemultiplexInput(input, augmentedStreamMap, Arrays.asList(commandInTarget)).start(); - return factory.apply(new ObjectInputStream(commandIn), commandOut); + return result[0] = factory.apply(new ObjectInputStream(commandIn), commandOut); } /** @@ -198,4 +245,13 @@ public class Util { } } + /** + * Log a serious unexpected internal exception. + * + * @param ex the exception + * @param where a description of the context of the exception + */ + private static void debug(Throwable ex, String where) { + // Reserved for future logging + } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/package-info.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/package-info.java index 3556132596a..7e96546d450 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/package-info.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/package-info.java @@ -46,7 +46,7 @@ * {@link jdk.jshell.SnippetEvent}. There are three major kinds of * changes to the status of a snippet: it can created with eval, * it can be dropped from the active source state with - * {@link jdk.jshell.JShell#drop(jdk.jshell.PersistentSnippet)}, and it can have + * {@link jdk.jshell.JShell#drop(jdk.jshell.Snippet)}, and it can have * its status updated as a result of a status change in another snippet. * For * example: given js, an instance of JShell, executing diff --git a/langtools/test/Makefile b/langtools/test/Makefile index f92e7611a97..e07635cca0a 100644 --- a/langtools/test/Makefile +++ b/langtools/test/Makefile @@ -157,11 +157,6 @@ ifdef TESTBOOTCLASSPATH -refvmoptions:-Xbootclasspath/p:$(TESTBOOTCLASSPATH) endif -ifeq ($(ARCH_DATA_MODEL),32) - # Set the GC options for test vms - JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC - JTREG_OPTIONS += $(JTREG_GC_OPTION) -endif # Set the max memory for jtreg target test JVMs JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx768m JTREG_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION) @@ -256,6 +251,17 @@ JTREG_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jtreg JCK_COMPILER_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-compiler JCK_RUNTIME_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-runtime-Xcompile +# Is the test JVM 32-bit? +DATA_MODEL := \ + $(shell $(JT_JAVA)/bin/java -XshowSettings:properties -version 2>&1 | \ + grep 'sun\.arch\.data\.model' | \ + awk '{print $$3}') +ifeq ($(DATA_MODEL), 32) + # Set the GC options for test vms having a smaller address space + JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC + JTREG_OPTIONS += $(JTREG_GC_OPTION) +endif + # Default make rule -- warning, may take a while all: $(JPRT_CLEAN) jtreg-tests jck-compiler-tests jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) all-summary @echo "Testing completed successfully" @@ -321,6 +327,7 @@ jtreg-tests: check-jtreg FRC $(JTREG_EXCLUSIONS) \ $(JTREG_OPTIONS) \ $(JTREG_TESTDIRS) \ + 2>&1 | tee $(JTREG_OUTPUT_DIR)/output.txt \ || ( $(call EXIT_IF_FATAL,$(FATAL_JTREG_EXIT)) ; \ echo $$status > $(JTREG_OUTPUT_DIR)/status.txt \ ) diff --git a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java index 652ef6690fe..7ce84428383 100644 --- a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java +++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 + * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8151921 * @summary Verify that the output has the right javascript. * @author jamieh * @library ../lib @@ -54,11 +54,12 @@ public class TestJavascript extends JavadocTester { checkOutput("index.html", true, "