--- a/make/InitSupport.gmk Wed Nov 29 22:35:35 2017 +0100
+++ b/make/InitSupport.gmk Wed Nov 29 22:40:23 2017 +0100
@@ -47,7 +47,7 @@
# Make control variables, handled by Init.gmk
INIT_CONTROL_VARIABLES += LOG CONF CONF_NAME SPEC JOBS TEST_JOBS CONF_CHECK \
- COMPARE_BUILD JTREG GTEST
+ COMPARE_BUILD JTREG GTEST TEST_OPTS TEST_VM_OPTS
# All known make control variables
MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER
--- a/make/Main.gmk Wed Nov 29 22:35:35 2017 +0100
+++ b/make/Main.gmk Wed Nov 29 22:40:23 2017 +0100
@@ -480,8 +480,7 @@
#
prepare-test-image:
- $(MKDIR) -p $(TEST_IMAGE_DIR)
- $(ECHO) > $(TEST_IMAGE_DIR)/Readme.txt 'JDK test image'
+ +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f TestImage.gmk prepare-test-image)
build-test-hotspot-jtreg-native:
+($(CD) $(TOPDIR)/make/test && $(MAKE) $(MAKE_ARGS) -f JtregNativeHotspot.gmk \
--- a/make/RunTests.gmk Wed Nov 29 22:35:35 2017 +0100
+++ b/make/RunTests.gmk Wed Nov 29 22:40:23 2017 +0100
@@ -32,8 +32,38 @@
# We will always run multiple tests serially
.NOTPARALLEL:
+################################################################################
+# Parse global control variables
+################################################################################
+
+ifneq ($(TEST_VM_OPTS), )
+ ifneq ($(TEST_OPTS), )
+ TEST_OPTS := $(TEST_OPTS);VM_OPTIONS=$(TEST_VM_OPTS)
+ else
+ TEST_OPTS := VM_OPTIONS=$(TEST_VM_OPTS)
+ endif
+endif
+
+$(eval $(call ParseKeywordVariable, TEST_OPTS, \
+ KEYWORDS := JOBS TIMEOUT, \
+ STRING_KEYWORDS := VM_OPTIONS, \
+))
+
+# Helper function to propagate TEST_OPTS values.
+#
+# Note: No spaces are allowed around the arguments.
+# Arg $1 The variable in TEST_OPTS to propagate
+# Arg $2 The control variable to propagate it to
+define SetTestOpt
+ ifneq ($$(TEST_OPTS_$1), )
+ $2_$1 := $$(TEST_OPTS_$1)
+ endif
+endef
+
+################################################################################
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, RunTests.gmk))
+################################################################################
TEST_RESULTS_DIR := $(OUTPUTDIR)/test-results
TEST_SUPPORT_DIR := $(OUTPUTDIR)/test-support
@@ -46,10 +76,33 @@
JTREG_TOPDIR := $(CUSTOM_ROOT)
endif
+JTREG_FAILURE_HANDLER_DIR := $(TEST_IMAGE_DIR)/failure_handler
+JTREG_FAILURE_HANDLER := $(JTREG_FAILURE_HANDLER_DIR)/jtregFailureHandler.jar
+
+ifneq ($(wildcard $(JTREG_FAILURE_HANDLER)), )
+ JTREG_FAILURE_HANDLER_OPTIONS := \
+ -timeoutHandlerDir:$(JTREG_FAILURE_HANDLER) \
+ -observerDir:$(JTREG_FAILURE_HANDLER) \
+ -timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler \
+ -observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \
+ -timeoutHandlerTimeout:0
+endif
+
################################################################################
# Parse control variables
################################################################################
+ifneq ($(TEST_OPTS), )
+ # Inform the user
+ $(info Running tests using TEST_OPTS control variable '$(TEST_OPTS)')
+
+ $(eval $(call SetTestOpt,VM_OPTIONS,JTREG))
+ $(eval $(call SetTestOpt,VM_OPTIONS,GTEST))
+
+ $(eval $(call SetTestOpt,JOBS,JTREG))
+ $(eval $(call SetTestOpt,TIMEOUT,JTREG))
+endif
+
$(eval $(call ParseKeywordVariable, JTREG, \
KEYWORDS := JOBS TIMEOUT TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM, \
STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS, \
@@ -62,7 +115,7 @@
$(eval $(call ParseKeywordVariable, GTEST, \
KEYWORDS := REPEAT, \
- STRING_KEYWORDS := OPTIONS, \
+ STRING_KEYWORDS := OPTIONS VM_OPTIONS, \
))
ifneq ($(GTEST), )
@@ -284,7 +337,7 @@
$$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/server/gtestLauncher \
-jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \
--gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \
- $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) \
+ $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \
> >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) && \
$$(ECHO) $$$$? > $$($1_EXITCODE) ||
$$(ECHO) $$$$? > $$($1_EXITCODE) \
@@ -296,15 +349,24 @@
$$(call LogWarn, Finished running test '$$($1_TEST)')
$$(call LogWarn, Test report is stored in $$(strip \
$$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
- $$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
- test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE)))
- $$(eval $1_PASSED := $$(shell $$(AWK) '/\[ PASSED \] .* tests?./ \
- { print $$$$4 }' $$($1_RESULT_FILE)))
- $$(eval $1_FAILED := $$(shell $$(AWK) '/\[ FAILED \] .* tests?, \
- listed below/ { print $$$$4 }' $$($1_RESULT_FILE)))
- $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0))
- $$(eval $1_ERROR := $$(shell \
- $$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED)))
+ $$(if $$(wildcard $$($1_RESULT_FILE)), \
+ $$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
+ test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE))) \
+ $$(if $$($1_TOTAL), , $$(eval $1_TOTAL := 0)) \
+ $$(eval $1_PASSED := $$(shell $$(AWK) '/\[ PASSED \] .* tests?./ \
+ { print $$$$4 }' $$($1_RESULT_FILE))) \
+ $$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \
+ $$(eval $1_FAILED := $$(shell $$(AWK) '/\[ FAILED \] .* tests?, \
+ listed below/ { print $$$$4 }' $$($1_RESULT_FILE))) \
+ $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \
+ $$(eval $1_ERROR := $$(shell \
+ $$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED))) \
+ , \
+ $$(eval $1_PASSED := 0) \
+ $$(eval $1_FAILED := 0) \
+ $$(eval $1_ERROR := 1) \
+ $$(eval $1_TOTAL := 1) \
+ )
$1: run-test-$1 parse-test-$1
@@ -429,6 +491,10 @@
$1_JTREG_BASIC_OPTIONS += -cpa:$$(JIB_JAR)
endif
+ ifneq ($$(JTREG_FAILURE_HANDLER_OPTIONS), )
+ $1_JTREG_LAUNCHER_OPTIONS += -Djava.library.path="$(JTREG_FAILURE_HANDLER_DIR)"
+ endif
+
clean-workdir-$1:
$$(RM) -r $$($1_TEST_SUPPORT_DIR)
@@ -445,6 +511,7 @@
-reportDir:$$($1_TEST_RESULTS_DIR) \
-workDir:$$($1_TEST_SUPPORT_DIR) \
$$(JTREG_OPTIONS) \
+ $$(JTREG_FAILURE_HANDLER_OPTIONS) \
$$($1_TEST_NAME) && \
$$(ECHO) $$$$? > $$($1_EXITCODE) ||
$$(ECHO) $$$$? > $$($1_EXITCODE) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/TestImage.gmk Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# 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.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+############################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+ FIXPATH_COPY := $(TEST_IMAGE_DIR)/bin/fixpath.exe
+
+ $(FIXPATH_COPY): $(firstword $(FIXPATH))
+ $(call install-file)
+endif
+
+prepare-test-image: $(FIXPATH_COPY)
+ $(call MakeDir, $(TEST_IMAGE_DIR))
+ $(ECHO) > $(TEST_IMAGE_DIR)/Readme.txt 'JDK test image'
+
+all: prepare-test-image
+
+.PHONY: default all prepare-test-image
--- a/make/nashorn/build.xml Wed Nov 29 22:35:35 2017 +0100
+++ b/make/nashorn/build.xml Wed Nov 29 22:40:23 2017 +0100
@@ -115,11 +115,11 @@
</target>
- <!-- check minimum ant version required to be 1.8.4 -->
+ <!-- check minimum ant version required to be 1.9.5 -->
<target name="check-ant-version">
- <property name="ant.version.required" value="1.8.4"/>
+ <property name="ant.version.required" value="1.9.5"/>
<antversion property="ant.current.version" />
- <fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.8.4 or above.">
+ <fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.9.5 or above.">
<condition>
<not>
<antversion atleast="${ant.version.required}"/>
--- a/src/java.base/share/classes/java/lang/ClassLoader.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java Wed Nov 29 22:40:23 2017 +0100
@@ -1813,7 +1813,7 @@
}
/**
- * Returns the platform class loader for delegation. All
+ * Returns the platform class loader. All
* <a href="#builtinLoaders">platform classes</a> are visible to
* the platform class loader.
*
@@ -1843,7 +1843,7 @@
}
/**
- * Returns the system class loader for delegation. This is the default
+ * Returns the system class loader. This is the default
* delegation parent for new {@code ClassLoader} instances, and is
* typically the class loader used to start the application.
*
@@ -1884,7 +1884,7 @@
* the application module path then the class path defaults to
* the current working directory.
*
- * @return The system {@code ClassLoader} for delegation
+ * @return The system {@code ClassLoader}
*
* @throws SecurityException
* If a security manager is present, and the caller's class loader
--- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java Wed Nov 29 22:40:23 2017 +0100
@@ -263,8 +263,12 @@
* methods from {@code Object}.
*
* @param caller Represents a lookup context with the accessibility
- * privileges of the caller. When used with {@code invokedynamic},
- * this is stacked automatically by the VM.
+ * privileges of the caller. Specifically, the lookup context
+ * must have
+ * <a href="MethodHandles.Lookup.html#privacc">private access</a>
+ * privileges.
+ * When used with {@code invokedynamic}, this is stacked
+ * automatically by the VM.
* @param invokedName The name of the method to implement. When used with
* {@code invokedynamic}, this is provided by the
* {@code NameAndType} of the {@code InvokeDynamic}
@@ -294,7 +298,8 @@
* instances of the interface named by {@code invokedType}
* @throws LambdaConversionException If any of the linkage invariants
* described {@link LambdaMetafactory above}
- * are violated
+ * are violated, or the lookup context
+ * does not have private access privileges.
*/
public static CallSite metafactory(MethodHandles.Lookup caller,
String invokedName,
@@ -404,8 +409,12 @@
* </ul>
*
* @param caller Represents a lookup context with the accessibility
- * privileges of the caller. When used with {@code invokedynamic},
- * this is stacked automatically by the VM.
+ * privileges of the caller. Specifically, the lookup context
+ * must have
+ * <a href="MethodHandles.Lookup.html#privacc">private access</a>
+ * privileges.
+ * When used with {@code invokedynamic}, this is stacked
+ * automatically by the VM.
* @param invokedName The name of the method to implement. When used with
* {@code invokedynamic}, this is provided by the
* {@code NameAndType} of the {@code InvokeDynamic}
@@ -429,7 +438,8 @@
* instances of the interface named by {@code invokedType}
* @throws LambdaConversionException If any of the linkage invariants
* described {@link LambdaMetafactory above}
- * are violated
+ * are violated, or the lookup context
+ * does not have private access privileges.
*/
public static CallSite altMetafactory(MethodHandles.Lookup caller,
String invokedName,
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Wed Nov 29 22:40:23 2017 +0100
@@ -385,9 +385,16 @@
* invoked, it returns the result of String concatenation, taking all
* function arguments passed to the linkage method as inputs for
* concatenation. The target signature is given by {@code concatType}.
- * The arguments are concatenated as per requirements stated in JLS 15.18.1
- * "String Concatenation Operator +". Notably, the inputs are converted as
- * per JLS 5.1.11 "String Conversion", and combined from left to right.
+ * For a target accepting:
+ * <ul>
+ * <li>zero inputs, concatenation results in an empty string;</li>
+ * <li>one input, concatenation results in the single
+ * input converted as per JLS 5.1.11 "String Conversion"; otherwise</li>
+ * <li>two or more inputs, the inputs are concatenated as per
+ * requirements stated in JLS 15.18.1 "String Concatenation Operator +".
+ * The inputs are converted as per JLS 5.1.11 "String Conversion",
+ * and combined from left to right.</li>
+ * </ul>
*
* <p>Assume the linkage arguments are as follows:
*
@@ -404,8 +411,12 @@
* </ul>
*
* @param lookup Represents a lookup context with the accessibility
- * privileges of the caller. When used with {@code
- * invokedynamic}, this is stacked automatically by the VM.
+ * privileges of the caller. Specifically, the lookup
+ * context must have
+ * <a href="MethodHandles.Lookup.html#privacc">private access</a>
+ * privileges.
+ * When used with {@code invokedynamic}, this is stacked
+ * automatically by the VM.
* @param name The name of the method to implement. This name is
* arbitrary, and has no meaning for this linkage method.
* When used with {@code invokedynamic}, this is provided by
@@ -422,7 +433,8 @@
* concatenation, with dynamic concatenation arguments described by the given
* {@code concatType}.
* @throws StringConcatException If any of the linkage invariants described
- * here are violated.
+ * here are violated, or the lookup context
+ * does not have private access privileges.
* @throws NullPointerException If any of the incoming arguments is null.
* This will never happen when a bootstrap method
* is called with invokedynamic.
@@ -452,10 +464,17 @@
* invoked, it returns the result of String concatenation, taking all
* function arguments and constants passed to the linkage method as inputs for
* concatenation. The target signature is given by {@code concatType}, and
- * does not include constants. The arguments are concatenated as per requirements
- * stated in JLS 15.18.1 "String Concatenation Operator +". Notably, the inputs
- * are converted as per JLS 5.1.11 "String Conversion", and combined from left
- * to right.
+ * does not include constants.
+ * For a target accepting:
+ * <ul>
+ * <li>zero inputs, concatenation results in an empty string;</li>
+ * <li>one input, concatenation results in the single
+ * input converted as per JLS 5.1.11 "String Conversion"; otherwise</li>
+ * <li>two or more inputs, the inputs are concatenated as per
+ * requirements stated in JLS 15.18.1 "String Concatenation Operator +".
+ * The inputs are converted as per JLS 5.1.11 "String Conversion",
+ * and combined from left to right.</li>
+ * </ul>
*
* <p>The concatenation <em>recipe</em> is a String description for the way to
* construct a concatenated String from the arguments and constants. The
@@ -502,9 +521,12 @@
* </ul>
*
* @param lookup Represents a lookup context with the accessibility
- * privileges of the caller. When used with {@code
- * invokedynamic}, this is stacked automatically by the
- * VM.
+ * privileges of the caller. Specifically, the lookup
+ * context must have
+ * <a href="MethodHandles.Lookup.html#privacc">private access</a>
+ * privileges.
+ * When used with {@code invokedynamic}, this is stacked
+ * automatically by the VM.
* @param name The name of the method to implement. This name is
* arbitrary, and has no meaning for this linkage method.
* When used with {@code invokedynamic}, this is provided
@@ -524,7 +546,8 @@
* concatenation, with dynamic concatenation arguments described by the given
* {@code concatType}.
* @throws StringConcatException If any of the linkage invariants described
- * here are violated.
+ * here are violated, or the lookup context
+ * does not have private access privileges.
* @throws NullPointerException If any of the incoming arguments is null, or
* any constant in {@code recipe} is null.
* This will never happen when a bootstrap method
--- a/src/java.base/share/classes/java/security/interfaces/DSAKeyPairGenerator.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/security/interfaces/DSAKeyPairGenerator.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,9 +32,12 @@
*
* <p>The {@code initialize} methods may each be called any number
* of times. If no {@code initialize} method is called on a
- * DSAKeyPairGenerator, the default is to generate 1024-bit keys, using
- * precomputed p, q and g parameters and an instance of SecureRandom as
- * the random bit source.
+ * DSAKeyPairGenerator, each provider that implements this interface
+ * should supply (and document) a default initialization. Note that
+ * defaults may vary across different providers. Additionally, the default
+ * value for a provider may change in a future version. Therefore, it is
+ * recommended to explicitly initialize the DSAKeyPairGenerator instead
+ * of relying on provider-specific defaults.
*
* <p>Users wishing to indicate DSA-specific parameters, and to generate a key
* pair suitable for use with the DSA algorithm typically
@@ -45,12 +48,13 @@
* KeyPairGenerator {@code getInstance} method with "DSA"
* as its argument.
*
- * <li>Initialize the generator by casting the result to a DSAKeyPairGenerator
- * and calling one of the
- * {@code initialize} methods from this DSAKeyPairGenerator interface.
+ * <li>Check if the returned key pair generator is an instance of
+ * DSAKeyPairGenerator before casting the result to a DSAKeyPairGenerator
+ * and calling one of the {@code initialize} methods from this
+ * DSAKeyPairGenerator interface.
*
* <li>Generate a key pair by calling the {@code generateKeyPair}
- * method from the KeyPairGenerator class.
+ * method of the KeyPairGenerator class.
*
* </ol>
*
@@ -63,7 +67,7 @@
* parameters.
*
* <p>Note: Some earlier implementations of this interface may not support
- * larger sizes of DSA parameters such as 2048 and 3072-bit.
+ * larger values of DSA parameters such as 3072-bit.
*
* @since 1.1
* @see java.security.KeyPairGenerator
@@ -97,8 +101,7 @@
* p, q and g parameters. If it is false, the method uses precomputed
* parameters for the modulus length requested. If there are no
* precomputed parameters for that modulus length, an exception will be
- * thrown. It is guaranteed that there will always be
- * default parameters for modulus lengths of 512 and 1024 bits.
+ * thrown.
*
* @param modlen the modulus length in bits. Valid values are any
* multiple of 64 between 512 and 1024, inclusive, 2048, and 3072.
--- a/src/java.base/share/classes/java/util/stream/DoubleStream.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/util/stream/DoubleStream.java Wed Nov 29 22:40:23 2017 +0100
@@ -1089,11 +1089,27 @@
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * <p>This method operates on the two input streams and binds each stream
+ * to its source. As a result subsequent modifications to an input stream
+ * source may not be reflected in the concatenated stream result.
+ *
* @implNote
* Use caution when constructing streams from repeated concatenation.
* Accessing an element of a deeply concatenated stream can result in deep
* call chains, or even {@code StackOverflowError}.
*
+ * @apiNote
+ * To preserve optimization opportunities this method binds each stream to
+ * its source and accepts only two streams as parameters. For example, the
+ * exact size of the concatenated stream source can be computed if the exact
+ * size of each input stream source is known.
+ * To concatenate more streams without binding, or without nested calls to
+ * this method, try creating a stream of streams and flat-mapping with the
+ * identity function, for example:
+ * <pre>{@code
+ * DoubleStream concat = Stream.of(s1, s2, s3, s4).flatMapToDouble(s -> s);
+ * }</pre>
+ *
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
--- a/src/java.base/share/classes/java/util/stream/IntStream.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/util/stream/IntStream.java Wed Nov 29 22:40:23 2017 +0100
@@ -1081,11 +1081,27 @@
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * <p>This method operates on the two input streams and binds each stream
+ * to its source. As a result subsequent modifications to an input stream
+ * source may not be reflected in the concatenated stream result.
+ *
* @implNote
* Use caution when constructing streams from repeated concatenation.
* Accessing an element of a deeply concatenated stream can result in deep
* call chains, or even {@code StackOverflowError}.
*
+ * @apiNote
+ * To preserve optimization opportunities this method binds each stream to
+ * its source and accepts only two streams as parameters. For example, the
+ * exact size of the concatenated stream source can be computed if the exact
+ * size of each input stream source is known.
+ * To concatenate more streams without binding, or without nested calls to
+ * this method, try creating a stream of streams and flat-mapping with the
+ * identity function, for example:
+ * <pre>{@code
+ * IntStream concat = Stream.of(s1, s2, s3, s4).flatMapToInt(s -> s);
+ * }</pre>
+ *
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
--- a/src/java.base/share/classes/java/util/stream/LongStream.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/util/stream/LongStream.java Wed Nov 29 22:40:23 2017 +0100
@@ -1086,11 +1086,27 @@
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * <p>This method operates on the two input streams and binds each stream
+ * to its source. As a result subsequent modifications to an input stream
+ * source may not be reflected in the concatenated stream result.
+ *
* @implNote
* Use caution when constructing streams from repeated concatenation.
* Accessing an element of a deeply concatenated stream can result in deep
* call chains, or even {@code StackOverflowError}.
*
+ * @apiNote
+ * To preserve optimization opportunities this method binds each stream to
+ * its source and accepts only two streams as parameters. For example, the
+ * exact size of the concatenated stream source can be computed if the exact
+ * size of each input stream source is known.
+ * To concatenate more streams without binding, or without nested calls to
+ * this method, try creating a stream of streams and flat-mapping with the
+ * identity function, for example:
+ * <pre>{@code
+ * LongStream concat = Stream.of(s1, s2, s3, s4).flatMapToLong(s -> s);
+ * }</pre>
+ *
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
--- a/src/java.base/share/classes/java/util/stream/Stream.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.base/share/classes/java/util/stream/Stream.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1341,6 +1341,10 @@
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * <p>This method operates on the two input streams and binds each stream
+ * to its source. As a result subsequent modifications to an input stream
+ * source may not be reflected in the concatenated stream result.
+ *
* @implNote
* Use caution when constructing streams from repeated concatenation.
* Accessing an element of a deeply concatenated stream can result in deep
@@ -1349,6 +1353,18 @@
* <p>Subsequent changes to the sequential/parallel execution mode of the
* returned stream are not guaranteed to be propagated to the input streams.
*
+ * @apiNote
+ * To preserve optimization opportunities this method binds each stream to
+ * its source and accepts only two streams as parameters. For example, the
+ * exact size of the concatenated stream source can be computed if the exact
+ * size of each input stream source is known.
+ * To concatenate more streams without binding, or without nested calls to
+ * this method, try creating a stream of streams and flat-mapping with the
+ * identity function, for example:
+ * <pre>{@code
+ * Stream<T> concat = Stream.of(s1, s2, s3, s4).flatMap(s -> s);
+ * }</pre>
+ *
* @param <T> The type of stream elements
* @param a the first stream
* @param b the second stream
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java Wed Nov 29 22:40:23 2017 +0100
@@ -257,7 +257,7 @@
*
* @implSpec This implementation dispatches to the visit method for
* the specific {@linkplain TypeKind kind} of pseudo-type:
- * {@code VOID}, {@code PACKAGE}, or {@code NONE}.
+ * {@code VOID}, {@code PACKAGE}, {@code MODULE}, or {@code NONE}.
*
* @param t {@inheritDoc}
* @param p {@inheritDoc}
@@ -273,6 +273,9 @@
case PACKAGE:
return visitNoTypeAsPackage(t, p);
+ case MODULE:
+ return visitNoTypeAsModule(t, p);
+
case NONE:
return visitNoTypeAsNone(t, p);
@@ -308,6 +311,21 @@
}
/**
+ * Visits a {@link TypeKind#MODULE MODULE} pseudo-type.
+ *
+ * @implSpec This implementation calls {@code visitUnknown}.
+ *
+ * @param t the type to visit
+ * @param p a visitor-specified parameter
+ * @return the result of {@code visitUnknown}
+ *
+ * @since 10
+ */
+ public R visitNoTypeAsModule(NoType t, P p) {
+ return visitUnknown(t, p);
+ }
+
+ /**
* Visits a {@link TypeKind#NONE NONE} pseudo-type.
*
* @implSpec This implementation calls {@code defaultAction}.
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor9.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor9.java Wed Nov 29 22:40:23 2017 +0100
@@ -93,4 +93,20 @@
protected TypeKindVisitor9(R defaultValue) {
super(defaultValue);
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @implSpec This implementation calls {@code defaultAction}.
+ *
+ * @param t {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of {@code defaultAction}
+ *
+ * @since 10
+ */
+ @Override
+ public R visitNoTypeAsModule(NoType t, P p) {
+ return defaultAction(t, p);
+ }
}
--- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -329,7 +329,7 @@
}
}
- private final void swap(final Vector<Object> a, final int i, final int j) {
+ private void swap(final Vector<Object> a, final int i, final int j) {
final Object T = a.elementAt(i);
a.setElementAt(a.elementAt(j), i);
a.setElementAt(T, j);
--- a/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1448,7 +1448,7 @@
*
* @return true during layout, false otherwise.
*/
- private final boolean isLayouting() {
+ private boolean isLayouting() {
return isLayouting;
}
}
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Wed Nov 29 22:40:23 2017 +0100
@@ -1359,14 +1359,18 @@
this.pixelStream = new DataInputStream(is);
/*
- * NB: the PNG spec declares that valid range for width
+ * PNG spec declares that valid range for width
* and height is [1, 2^31-1], so here we may fail to allocate
* a buffer for destination image due to memory limitation.
*
- * However, the recovery strategy for this case should be
- * defined on the level of application, so we will not
- * try to estimate the required amount of the memory and/or
- * handle OOM in any way.
+ * If the read operation triggers OutOfMemoryError, the same
+ * will be wrapped in an IIOException at PNGImageReader.read
+ * method.
+ *
+ * The recovery strategy for this case should be defined at
+ * the level of application, so we will not try to estimate
+ * the required amount of the memory and/or handle OOM in
+ * any way.
*/
theImage = getDestination(param,
getImageTypes(0),
@@ -1671,7 +1675,16 @@
throw new IndexOutOfBoundsException("imageIndex != 0!");
}
- readImage(param);
+ try {
+ readImage(param);
+ } catch (IOException |
+ IllegalStateException |
+ IllegalArgumentException e)
+ {
+ throw e;
+ } catch (Throwable e) {
+ throw new IIOException("Caught exception during read: ", e);
+ }
return theImage;
}
@@ -1685,5 +1698,6 @@
gotMetadata = false;
metadata = null;
pixelStream = null;
+ imageStartPosition = -1L;
}
}
--- a/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
private final String fourcc;
private String riff_type = null;
private final long ckSize;
- private InputStream stream;
+ private final InputStream stream;
private long avail = 0xffffffffL; // MAX_UNSIGNED_INT
private RIFFReader lastiterator = null;
@@ -338,8 +338,6 @@
@Override
public void close() throws IOException {
finish();
- if (this == root)
- stream.close();
- stream = null;
+ stream.close();
}
}
--- a/src/java.desktop/share/classes/java/awt/Component.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/Component.java Wed Nov 29 22:40:23 2017 +0100
@@ -1135,9 +1135,18 @@
if (graphicsConfig == gc) {
return false;
}
-
+ GraphicsConfiguration oldConfig = graphicsConfig;
graphicsConfig = gc;
+ /*
+ * If component is moved from one screen to another sceeen
+ * graphicsConfiguration property is fired to enable the component
+ * to recalculate any rendering data, if needed
+ */
+ if (oldConfig != null && gc != null) {
+ firePropertyChange("graphicsConfiguration", oldConfig, gc);
+ }
+
ComponentPeer peer = this.peer;
if (peer != null) {
return peer.updateGraphicsData(gc);
@@ -2030,14 +2039,14 @@
* used by GlobalCursormanager to update cursor
*/
final Point getLocationOnScreen_NoTreeLock() {
-
+ ComponentPeer peer = this.peer;
if (peer != null && isShowing()) {
if (peer instanceof LightweightPeer) {
// lightweight component location needs to be translated
// relative to a native component.
Container host = getNativeContainer();
Point pt = host.peer.getLocationOnScreen();
- for(Component c = this; c != host; c = c.getParent()) {
+ for(Component c = this; c != host; c = c.getContainer()) {
pt.x += c.x;
pt.y += c.y;
}
@@ -10218,7 +10227,7 @@
applyCompoundShape(getAppliedShape().getDifference(s));
}
- private final void applyCurrentShapeBelowMe() {
+ private void applyCurrentShapeBelowMe() {
checkTreeLock();
Container parent = getContainer();
if (parent != null && parent.isShowing()) {
--- a/src/java.desktop/share/classes/java/awt/EventQueue.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/EventQueue.java Wed Nov 29 22:40:23 2017 +0100
@@ -283,7 +283,7 @@
* @param theEvent an instance of {@code java.awt.AWTEvent},
* or a subclass of it
*/
- private final void postEventPrivate(AWTEvent theEvent) {
+ private void postEventPrivate(AWTEvent theEvent) {
theEvent.isPosted = true;
pushPopLock.lock();
try {
--- a/src/java.desktop/share/classes/java/awt/MenuItem.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/MenuItem.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -410,7 +410,7 @@
* Returns true if the item and all its ancestors are
* enabled, false otherwise
*/
- private final boolean isItemEnabled() {
+ private boolean isItemEnabled() {
// Fix For 6185151: Menu shortcuts of all menuitems within a menu
// should be disabled when the menu itself is disabled
if (!isEnabled()) {
--- a/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/geom/AffineTransform.java Wed Nov 29 22:40:23 2017 +0100
@@ -1354,7 +1354,7 @@
/* SH | SC => */ APPLY_SHEAR | APPLY_SCALE,
/* SH | SC | TR => */ APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE,
};
- private final void rotate90() {
+ private void rotate90() {
double M0 = m00;
m00 = m01;
m01 = -M0;
@@ -1370,7 +1370,7 @@
this.state = state;
type = TYPE_UNKNOWN;
}
- private final void rotate180() {
+ private void rotate180() {
m00 = -m00;
m11 = -m11;
int state = this.state;
@@ -1390,7 +1390,7 @@
}
type = TYPE_UNKNOWN;
}
- private final void rotate270() {
+ private void rotate270() {
double M0 = m00;
m00 = -m01;
m01 = M0;
--- a/src/java.desktop/share/classes/java/awt/image/BufferedImageFilter.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/image/BufferedImageFilter.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -397,7 +397,7 @@
consumer.imageComplete(status);
}
- private final WritableRaster createDCMraster() {
+ private WritableRaster createDCMraster() {
WritableRaster wr;
DirectColorModel dcm = (DirectColorModel) model;
boolean hasAlpha = model.hasAlpha();
--- a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -295,7 +295,7 @@
}
}
- private final BufferedImage ICCBIFilter(BufferedImage src,
+ private BufferedImage ICCBIFilter(BufferedImage src,
ColorSpace srcColorSpace,
BufferedImage dest,
ColorSpace destColorSpace) {
@@ -753,7 +753,7 @@
return hints;
}
- private final BufferedImage nonICCBIFilter(BufferedImage src,
+ private BufferedImage nonICCBIFilter(BufferedImage src,
ColorSpace srcColorSpace,
BufferedImage dst,
ColorSpace dstColorSpace) {
@@ -947,7 +947,7 @@
/* color convert a Raster - handles byte, ushort, int, short, float,
or double transferTypes */
- private final WritableRaster nonICCRasterFilter(Raster src,
+ private WritableRaster nonICCRasterFilter(Raster src,
WritableRaster dst) {
if (CSList.length != 2) {
--- a/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java Wed Nov 29 22:40:23 2017 +0100
@@ -755,7 +755,7 @@
* value is used to mask off the pixel parameters for methods such
* as getRed(), getGreen(), getBlue(), getAlpha(), and getRGB().
*/
- private final void calculatePixelMask() {
+ private void calculatePixelMask() {
// Note that we adjust the mask so that our masking behavior here
// is consistent with that of our native rendering loops.
int maskbits = pixel_bits;
--- a/src/java.desktop/share/classes/java/awt/image/LookupOp.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/image/LookupOp.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -472,7 +472,7 @@
return hints;
}
- private final void byteFilter(ByteLookupTable lookup, Raster src,
+ private void byteFilter(ByteLookupTable lookup, Raster src,
WritableRaster dst,
int width, int height, int numBands) {
int[] srcPix = null;
@@ -519,7 +519,7 @@
}
}
- private final void shortFilter(ShortLookupTable lookup, Raster src,
+ private void shortFilter(ShortLookupTable lookup, Raster src,
WritableRaster dst,
int width, int height, int numBands) {
int band;
--- a/src/java.desktop/share/classes/java/awt/image/LookupTable.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/java/awt/image/LookupTable.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
* @see ShortLookupTable
* @see LookupOp
*/
-public abstract class LookupTable extends Object{
+public abstract class LookupTable {
/**
* Constants
--- a/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -775,8 +775,7 @@
* transform. If you need to do these operations you may find it
* easier to create a new <code>Graphics</code> from the passed in
* <code>Graphics</code> and manipulate it. Further, if you do not
- * invoker super's implementation you must honor the opaque property,
- * that is
+ * invoke super's implementation you must honor the opaque property, that is
* if this component is opaque, you must completely fill in the background
* in an opaque color. If you do not honor the opaque property you
* will likely see visual artifacts.
--- a/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -102,7 +102,7 @@
/* A null array to be shared by all empty listener lists*/
private static final Object[] NULL_ARRAY = new Object[0];
/** The list of ListenerType - Listener pairs */
- protected transient Object[] listenerList = NULL_ARRAY;
+ protected transient volatile Object[] listenerList = NULL_ARRAY;
/**
* Passes back the event listener list as an array
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java Wed Nov 29 22:40:23 2017 +0100
@@ -75,7 +75,8 @@
checkOpacity((AbstractButton) e.getSource() );
}
else if(prop == AbstractButton.TEXT_CHANGED_PROPERTY ||
- "font" == prop || "foreground" == prop) {
+ "font" == prop || "foreground" == prop ||
+ "ancestor" == prop || "graphicsConfiguration" == prop) {
AbstractButton b = (AbstractButton) e.getSource();
BasicHTML.updateRenderer(b, b.getText());
}
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java Wed Nov 29 22:40:23 2017 +0100
@@ -472,7 +472,8 @@
public void propertyChange(PropertyChangeEvent e) {
String name = e.getPropertyName();
- if (name == "text" || "font" == name || "foreground" == name) {
+ if (name == "text" || "font" == name || "foreground" == name ||
+ "ancestor" == name || "graphicsConfiguration" == name) {
// remove the old html view client property if one
// existed, and install a new one if the text installed
// into the JLabel is html source.
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java Wed Nov 29 22:40:23 2017 +0100
@@ -1106,7 +1106,8 @@
name == "accelerator") {
updateAcceleratorBinding();
} else if (name == "text" || "font" == name ||
- "foreground" == name) {
+ "foreground" == name ||
+ "ancestor" == name || "graphicsConfiguration" == name) {
// remove the old html view client property if one
// existed, and install a new one if the text installed
// into the JLabel is html source.
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java Wed Nov 29 22:40:23 2017 +0100
@@ -226,8 +226,13 @@
return (MenuKeyListener)getHandler();
}
+ public Dimension getMinimumSize(JComponent c) {
+ return (((JMenu)menuItem).isTopLevelMenu()) ?
+ c.getPreferredSize() : null;
+ }
+
public Dimension getMaximumSize(JComponent c) {
- if (((JMenu)menuItem).isTopLevelMenu() == true) {
+ if (((JMenu)menuItem).isTopLevelMenu()) {
Dimension d = c.getPreferredSize();
return new Dimension(d.width, Short.MAX_VALUE);
}
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolTipUI.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolTipUI.java Wed Nov 29 22:40:23 2017 +0100
@@ -261,7 +261,8 @@
public void propertyChange(PropertyChangeEvent e) {
String name = e.getPropertyName();
if (name.equals("tiptext") || "font".equals(name) ||
- "foreground".equals(name)) {
+ "foreground".equals(name) ||
+ "ancestor" == name || "graphicsConfiguration" == name) {
// remove the old html view client property if one
// existed, and install a new one if the text installed
// into the JLabel is html source.
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3490,7 +3490,7 @@
* the destination it is constructed with. It is assumed all the
* events are currently target at source.
*/
- public class MouseInputHandler extends Object implements
+ public class MouseInputHandler implements
MouseInputListener
{
/** Source that events are coming from. */
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java Wed Nov 29 22:40:23 2017 +0100
@@ -227,7 +227,8 @@
}
String name = e.getPropertyName();
if (name.equals("tiptext") || "font".equals(name) ||
- "foreground".equals(name)) {
+ "foreground".equals(name) ||
+ "ancestor" == name || "graphicsConfiguration" == name) {
// remove the old html view client property if one
// existed, and install a new one if the text installed
// into the JLabel is html source.
--- a/src/java.desktop/share/classes/javax/swing/table/TableColumn.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/table/TableColumn.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -83,7 +83,7 @@
* @see JTable#getCellEditor(int, int)
*/
@SuppressWarnings("serial") // Same-version serialization only
-public class TableColumn extends Object implements Serializable {
+public class TableColumn implements Serializable {
/**
* Obsolete as of Java 2 platform v1.3. Please use string literals to identify
--- a/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1797,7 +1797,7 @@
}
}
- private final void indent(PrintWriter out, int n) {
+ private void indent(PrintWriter out, int n) {
for (int i = 0; i < n; i++) {
out.print(" ");
}
@@ -2063,7 +2063,7 @@
}
}
- private final void checkForIllegalCast() {
+ private void checkForIllegalCast() {
Thread t = getCurrentWriter();
if ((t == null) || (t != Thread.currentThread())) {
throw new StateInvariantError("Illegal cast to MutableAttributeSet");
--- a/src/java.desktop/share/classes/javax/swing/text/GlyphPainter1.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/text/GlyphPainter1.java Wed Nov 29 22:40:23 2017 +0100
@@ -59,7 +59,8 @@
sync(v);
Segment text = v.getText(p0, p1);
int[] justificationData = getJustificationData(v);
- int width = Utilities.getTabbedTextWidth(v, text, metrics, (int) x, e, p0,
+
+ int width = Utilities.getTabbedTextWidth(v, text, metrics, (int)x, e, p0,
justificationData);
SegmentCache.releaseSharedSegment(text);
return width;
@@ -222,10 +223,15 @@
@SuppressWarnings("deprecation")
void sync(GlyphView v) {
Font f = v.getFont();
- if ((metrics == null) || (! f.equals(metrics.getFont()))) {
+ FontMetrics fm = null;
+ Container c = v.getContainer();
+ if (c != null) {
+ fm = c.getFontMetrics(f);
+ }
+ if ((metrics == null) || (! f.equals(metrics.getFont()))
+ || (! metrics.equals(fm))) {
// fetch a new FontMetrics
- Container c = v.getContainer();
- metrics = (c != null) ? c.getFontMetrics(f) :
+ metrics = (c != null) ? fm :
Toolkit.getDefaultToolkit().getFontMetrics(f);
}
}
--- a/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2422,7 +2422,7 @@
private int currentPosition;
- private final int readCh() throws IOException {
+ private int readCh() throws IOException {
if (pos >= len) {
--- a/src/java.desktop/share/classes/javax/swing/tree/TreePath.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/javax/swing/tree/TreePath.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,7 +82,7 @@
* @author Philip Milne
*/
@SuppressWarnings("serial") // Same-version serialization only
-public class TreePath extends Object implements Serializable {
+public class TreePath implements Serializable {
/** Path representing the parent, null if lastPathComponent represents
* the root. */
private TreePath parentPath;
--- a/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,7 @@
private void property(String key,float value) {
property(key, Float.valueOf(value));
}
- private final void pngassert(boolean b) throws IOException {
+ private void pngassert(boolean b) throws IOException {
if(!b) {
PNGException e = new PNGException("Broken file");
e.printStackTrace();
@@ -692,20 +692,20 @@
fill();
return limit-pos>=n;
}
- private final int getInt(int pos) {
+ private int getInt(int pos) {
return ((inbuf[pos ]&0xFF)<<24)
| ((inbuf[pos+1]&0xFF)<<16)
| ((inbuf[pos+2]&0xFF)<< 8)
| ((inbuf[pos+3]&0xFF) );
}
- private final int getShort(int pos) {
+ private int getShort(int pos) {
return (short)(((inbuf[pos ]&0xFF)<<8)
| ((inbuf[pos+1]&0xFF) ));
}
- private final int getByte(int pos) {
+ private int getByte(int pos) {
return inbuf[pos]&0xFF;
}
- private final boolean getChunk() throws IOException {
+ private boolean getChunk() throws IOException {
chunkLength = 0;
if (!need(8)) return false;
chunkLength = getInt(pos);
--- a/src/java.desktop/share/classes/sun/awt/image/SunVolatileImage.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/awt/image/SunVolatileImage.java Wed Nov 29 22:40:23 2017 +0100
@@ -40,6 +40,7 @@
import sun.java2d.SurfaceManagerFactory;
import sun.java2d.DestSurfaceProvider;
import sun.java2d.Surface;
+import sun.java2d.pipe.Region;
import static sun.java2d.pipe.hw.AccelSurface.*;
/**
@@ -245,8 +246,8 @@
* or a backup surface with the given horizontal and vertical scale factors.
*/
public BufferedImage getBackupImage(double scaleX, double scaleY) {
- int w = (int) Math.ceil(getWidth() * scaleX);
- int h = (int) Math.ceil(getHeight() * scaleY);
+ int w = Region.clipRound(getWidth() * scaleX);
+ int h = Region.clipRound(getHeight() * scaleY);
return graphicsConfig.createCompatibleImage(w, h, getTransparency());
}
--- a/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -310,7 +310,7 @@
return new Rectangle2D.Float(l, t, r - l, b - t);
}
- private final StandardGlyphVector getGV() {
+ private StandardGlyphVector getGV() {
if (gv == null) {
gv = createGV();
}
@@ -543,7 +543,7 @@
}
}
- private final float[] getCharinfo() {
+ private float[] getCharinfo() {
if (charinfo == null) {
charinfo = createCharinfo();
}
--- a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -998,14 +998,14 @@
}
// called by getGlyphsPixelBounds
- private final void setDTX(AffineTransform tx) {
+ private void setDTX(AffineTransform tx) {
if (!equalNonTranslateTX(dtx, tx)) {
resetDTX(getNonTranslateTX(tx));
}
}
// called by most functions
- private final void setFRCTX() {
+ private void setFRCTX() {
if (!equalNonTranslateTX(frctx, dtx)) {
resetDTX(getNonTranslateTX(frctx));
}
@@ -1016,7 +1016,7 @@
* must not contain translation.
* Called by setRenderTransform, setDTX, initFontData.
*/
- private final void resetDTX(AffineTransform at) {
+ private void resetDTX(AffineTransform at) {
fsref = null;
dtx = at;
invdtx = null;
--- a/src/java.desktop/share/classes/sun/font/TextSourceLabel.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/font/TextSourceLabel.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -147,7 +147,7 @@
return createLogicalBounds();
}
- private final GlyphVector getGV() {
+ private GlyphVector getGV() {
if (gv == null) {
gv = createGV();
}
--- a/src/java.desktop/share/classes/sun/font/TrueTypeGlyphMapper.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/font/TrueTypeGlyphMapper.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -106,11 +106,11 @@
cmap = CMap.theNullCmap;
}
- private final char remapJAChar(char unicode) {
+ private char remapJAChar(char unicode) {
return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
}
- private final int remapJAIntChar(int unicode) {
+ private int remapJAIntChar(int unicode) {
return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
}
--- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java Wed Nov 29 22:40:23 2017 +0100
@@ -3146,6 +3146,14 @@
double widthScale = ((double) rvWidth) / width;
double heightScale = ((double) rvHeight) / height;
+ if (resolutionVariant instanceof VolatileImage) {
+ SurfaceData sd = SurfaceManager
+ .getManager(resolutionVariant)
+ .getPrimarySurfaceData();
+ widthScale *= sd.getDefaultScaleX();
+ heightScale *= sd.getDefaultScaleY();
+ }
+
sx1 = Region.clipScale(sx1, widthScale);
sy1 = Region.clipScale(sy1, heightScale);
sx2 = Region.clipScale(sx2, widthScale);
--- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java Wed Nov 29 22:40:23 2017 +0100
@@ -227,7 +227,7 @@
pc2d);
}
- private final double userSpaceLineWidth(AffineTransform at, double lw) {
+ private double userSpaceLineWidth(AffineTransform at, double lw) {
double widthScale;
--- a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java Wed Nov 29 22:40:23 2017 +0100
@@ -227,7 +227,7 @@
pc2d);
}
- private final float userSpaceLineWidth(AffineTransform at, float lw) {
+ private float userSpaceLineWidth(AffineTransform at, float lw) {
float widthScale;
--- a/src/java.desktop/share/classes/sun/swing/AccumulativeRunnable.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/swing/AccumulativeRunnable.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -152,7 +152,7 @@
*
* @return accumulated arguments
*/
- private final synchronized List<T> flush() {
+ private synchronized List<T> flush() {
List<T> list = arguments;
arguments = null;
return list;
--- a/src/java.desktop/share/classes/sun/swing/CachedPainter.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/share/classes/sun/swing/CachedPainter.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,21 @@
*/
package sun.swing;
-import java.awt.*;
-import java.awt.image.*;
-import java.util.*;
+import sun.awt.image.SurfaceManager;
+import sun.java2d.SurfaceData;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AbstractMultiResolutionImage;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.awt.image.VolatileImage;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
/**
* A base class used for icons or images that are expensive to paint.
@@ -129,6 +141,22 @@
}
if (image == null) {
// Recreate the image
+ if( config != null && (w != baseHeight || h != baseWidth)) {
+ AffineTransform tx = config.getDefaultTransform();
+ double sx = tx.getScaleX();
+ double sy = tx.getScaleY();
+ if ( Double.compare(sx, 1) != 0 ||
+ Double.compare(sy, 1) != 0) {
+ if (Math.abs(sx * baseWidth - w) < 1 &&
+ Math.abs(sy * baseHeight - h) < 1) {
+ w = baseWidth;
+ h = baseHeight;
+ } else {
+ w = (int)Math.ceil(w / sx);
+ h = (int)Math.ceil(w / sy);
+ }
+ }
+ }
image = createImage(c, w, h, config, args);
cache.setImage(key, config, w, h, args, image);
draw = true;
@@ -139,10 +167,24 @@
if (draw) {
// Render to the Image
Graphics2D g2 = (Graphics2D) image.getGraphics();
- if (volatileImage == null && (w != baseWidth || h != baseHeight)) {
- g2.scale((double) w / baseWidth, (double) h / baseHeight);
+ if (volatileImage == null) {
+ if ((w != baseWidth || h != baseHeight)) {
+ g2.scale((double) w / baseWidth,
+ (double) h / baseHeight);
+ }
+ paintToImage(c, image, g2, baseWidth, baseHeight, args);
+ } else {
+ SurfaceData sd = SurfaceManager.getManager(volatileImage)
+ .getPrimarySurfaceData();
+ double sx = sd.getDefaultScaleX();
+ double sy = sd.getDefaultScaleY();
+ if ( Double.compare(sx, 1) != 0 ||
+ Double.compare(sy, 1) != 0) {
+ g2.scale(1 / sx, 1 / sy);
+ }
+ paintToImage(c, image, g2, (int)Math.ceil(w * sx),
+ (int)Math.ceil(h * sy), args);
}
- paintToImage(c, image, g2, baseWidth, baseHeight, args);
g2.dispose();
}
@@ -288,4 +330,4 @@
return Arrays.asList(getResolutionVariant(baseWidth, baseHeight));
}
}
-}
\ No newline at end of file
+}
--- a/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* 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 @@
// internal lock for synchronizing state changes and paint calls, initialized in preInit.
// the order with other locks: AWTLock -> stateLock
- static class StateLock extends Object { }
+ static class StateLock { }
protected StateLock state_lock;
/**
@@ -315,7 +315,7 @@
* Creates window with parameters specified by {@code params}
* @see #init
*/
- private final void create(XCreateWindowParams params) {
+ private void create(XCreateWindowParams params) {
XToolkit.awtLock();
try {
XSetWindowAttributes xattr = new XSetWindowAttributes();
--- a/src/java.desktop/unix/classes/sun/java2d/x11/X11Renderer.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/unix/classes/sun/java2d/x11/X11Renderer.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
: new X11Renderer());
}
- private final long validate(SunGraphics2D sg2d) {
+ private long validate(SunGraphics2D sg2d) {
// NOTE: getCompClip() will revalidateAll() if the
// surfaceData is invalid. This should ensure that
// the clip and pixel that we are validating against
--- a/src/java.desktop/unix/classes/sun/java2d/xr/XRRenderer.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRRenderer.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
* Common validate method, used by all XRRender functions to validate the
* destination context.
*/
- private final void validateSurface(SunGraphics2D sg2d) {
+ private void validateSurface(SunGraphics2D sg2d) {
XRSurfaceData xrsd;
try {
xrsd = (XRSurfaceData) sg2d.surfaceData;
--- a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java Wed Nov 29 22:40:23 2017 +0100
@@ -498,7 +498,7 @@
// set Clause and Reading Information
if (clauseBoundary!=null && clauseReading!=null &&
clauseReading.length!=0 && clauseBoundary.length==clauseReading.length+1 &&
- clauseBoundary[0]==0 && clauseBoundary[clauseReading.length]==text.length() )
+ clauseBoundary[0]==0 && clauseBoundary[clauseReading.length]<=text.length() )
{
for (int i=0; i<clauseBoundary.length-1; i++) {
attrStr.addAttribute(Attribute.INPUT_METHOD_SEGMENT,
--- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java Wed Nov 29 22:40:23 2017 +0100
@@ -630,7 +630,7 @@
private native void nativeGrab();
private native void nativeUngrab();
- private final boolean hasWarningWindow() {
+ private boolean hasWarningWindow() {
return ((Window)target).getWarningString() != null;
}
@@ -674,7 +674,7 @@
super.setBounds(x, y, width, height, op);
}
- private final void initScales() {
+ private void initScales() {
if (scaleX >= 1 && scaleY >= 1) {
return;
--- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Wed Nov 29 22:40:23 2017 +0100
@@ -58,6 +58,7 @@
import sun.java2d.pipe.PixelToParallelogramConverter;
import sun.java2d.pipe.RenderBuffer;
import sun.java2d.pipe.TextPipe;
+import sun.java2d.pipe.Region;
import static sun.java2d.pipe.BufferedOpCodes.*;
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
@@ -236,8 +237,8 @@
this.width = scaledSize.width;
this.height = scaledSize.height;
} else {
- this.width = (int) Math.ceil(width * scaleX);
- this.height = (int) Math.ceil(height * scaleY);
+ this.width = Region.clipRound(width * scaleX);
+ this.height = Region.clipRound(height * scaleY);
}
this.offscreenImage = image;
@@ -812,8 +813,8 @@
double scaleY = getDefaultScaleY();
Rectangle r = peer.getBounds();
r.x = r.y = 0;
- r.width = (int) Math.ceil(r.width * scaleX);
- r.height = (int) Math.ceil(r.height * scaleY);
+ r.width = Region.clipRound(r.width * scaleX);
+ r.height = Region.clipRound(r.height * scaleY);
return r;
} else {
return new Rectangle(width, height);
--- a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java Wed Nov 29 22:40:23 2017 +0100
@@ -37,6 +37,7 @@
import sun.awt.Win32GraphicsDevice;
import sun.awt.windows.WComponentPeer;
import sun.java2d.SurfaceData;
+import sun.java2d.pipe.Region;
public abstract class WGLSurfaceData extends OGLSurfaceData {
@@ -165,8 +166,8 @@
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
- r.width = (int) Math.ceil(r.width * scaleX);
- r.height = (int) Math.ceil(r.height * scaleY);
+ r.width = Region.clipRound(r.width * scaleX);
+ r.height = Region.clipRound(r.height * scaleY);
return r;
}
@@ -227,8 +228,8 @@
{
super(peer, gc, cm, type);
- this.width = (int) Math.ceil(width * scaleX);
- this.height = (int) Math.ceil(height * scaleY);
+ this.width = Region.clipRound(width * scaleX);
+ this.height = Region.clipRound(height * scaleY);
offscreenImage = image;
initSurface(this.width, this.height);
@@ -241,8 +242,8 @@
public Rectangle getBounds() {
if (type == FLIP_BACKBUFFER) {
Rectangle r = peer.getBounds();
- r.width = (int) Math.ceil(r.width * scaleX);
- r.height = (int) Math.ceil(r.height * scaleY);
+ r.width = Region.clipRound(r.width * scaleX);
+ r.height = Region.clipRound(r.height * scaleY);
r.x = r.y = 0;
return r;
} else {
--- a/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java Wed Nov 29 22:40:23 2017 +0100
@@ -302,8 +302,8 @@
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
- r.width = (int) Math.ceil(r.width * scaleX);
- r.height = (int) Math.ceil(r.height * scaleY);
+ r.width = Region.clipRound(r.width * scaleX);
+ r.height = Region.clipRound(r.height * scaleY);
return r;
}
--- a/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp Wed Nov 29 22:35:35 2017 +0100
+++ b/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -202,9 +202,15 @@
m_lpClauseW == NULL || m_lpReadClauseW == NULL ||
m_lpClauseW[0] != 0 || m_lpClauseW[m_cClauseW] != (DWORD)m_cStrW ||
m_lpReadClauseW[0] != 0 || m_lpReadClauseW[m_cReadClauseW] != (DWORD)m_cReadStrW) {
- lpBndClauseW = NULL;
- lpReadingClauseW = NULL;
- return 0;
+ // For cases where IMM sends WM_IME_COMPOSITION with both GCS_COMPSTR and GCS_RESULTSTR
+ // The GCS_RESULTSTR part may have Caluse and Reading information which should not be ignored
+ if (NULL == m_pResultTextInfor) {
+ lpBndClauseW = NULL;
+ lpReadingClauseW = NULL;
+ return 0;
+ } else {
+ return m_pResultTextInfor->GetClauseInfor(lpBndClauseW, lpReadingClauseW);
+ }
}
int* bndClauseW = NULL;
@@ -346,10 +352,14 @@
//
int AwtInputTextInfor::GetAttributeInfor(int*& lpBndAttrW, BYTE*& lpValAttrW) {
if (m_cStrW == 0 || m_cAttrW != m_cStrW) {
- lpBndAttrW = NULL;
- lpValAttrW = NULL;
+ if (NULL == m_pResultTextInfor) {
+ lpBndAttrW = NULL;
+ lpValAttrW = NULL;
- return 0;
+ return 0;
+ } else {
+ return m_pResultTextInfor->GetAttributeInfor(lpBndAttrW, lpValAttrW);
+ }
}
int* bndAttrW = NULL;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Nov 29 22:40:23 2017 +0100
@@ -237,7 +237,7 @@
* {@code upwards(List<#CAP1>, [#CAP2]) = List<#CAP1> }
* {@code downwards(List<#CAP1>, [#CAP1]) = not defined }
*/
- class TypeProjection extends StructuralTypeMapping<ProjectionKind> {
+ class TypeProjection extends TypeMapping<ProjectionKind> {
List<Type> vars;
Set<Type> seen = new HashSet<>();
@@ -257,13 +257,21 @@
Type outer = t.getEnclosingType();
Type outer1 = visit(outer, pkind);
List<Type> typarams = t.getTypeArguments();
- List<Type> typarams1 = typarams.map(ta -> mapTypeArgument(ta, pkind));
- if (typarams1.stream().anyMatch(ta -> ta.hasTag(BOT))) {
- //not defined
- return syms.botType;
+ List<Type> formals = t.tsym.type.getTypeArguments();
+ ListBuffer<Type> typarams1 = new ListBuffer<>();
+ boolean changed = false;
+ for (Type actual : typarams) {
+ Type t2 = mapTypeArgument(t, formals.head.getUpperBound(), actual, pkind);
+ if (t2.hasTag(BOT)) {
+ //not defined
+ return syms.botType;
+ }
+ typarams1.add(t2);
+ changed |= actual != t2;
+ formals = formals.tail;
}
- if (outer1 == outer && typarams1 == typarams) return t;
- else return new ClassType(outer1, typarams1, t.tsym, t.getMetadata()) {
+ if (outer1 == outer && !changed) return t;
+ else return new ClassType(outer1, typarams1.toList(), t.tsym, t.getMetadata()) {
@Override
protected boolean needsStripping() {
return true;
@@ -272,21 +280,23 @@
}
}
- protected Type makeWildcard(Type upper, Type lower) {
- BoundKind bk;
- Type bound;
- if (upper.hasTag(BOT)) {
- upper = syms.objectType;
- }
- boolean isUpperObject = isSameType(upper, syms.objectType);
- if (!lower.hasTag(BOT) && isUpperObject) {
- bound = lower;
- bk = SUPER;
+ @Override
+ public Type visitArrayType(ArrayType t, ProjectionKind s) {
+ Type elemtype = t.elemtype;
+ Type elemtype1 = visit(elemtype, s);
+ if (elemtype1 == elemtype) {
+ return t;
+ } else if (elemtype1.hasTag(BOT)) {
+ //undefined
+ return syms.botType;
} else {
- bound = upper;
- bk = isUpperObject ? UNBOUND : EXTENDS;
- }
- return new WildcardType(bound, bk, syms.boundClass);
+ return new ArrayType(elemtype1, t.tsym, t.metadata) {
+ @Override
+ protected boolean needsStripping() {
+ return true;
+ }
+ };
+ }
}
@Override
@@ -322,33 +332,79 @@
}
}
- @Override
- public Type visitWildcardType(WildcardType wt, ProjectionKind pkind) {
- switch (pkind) {
- case UPWARDS:
- return wt.isExtendsBound() ?
- wt.type.map(this, pkind) :
- syms.objectType;
- case DOWNWARDS:
- return wt.isSuperBound() ?
- wt.type.map(this, pkind) :
- syms.botType;
- default:
- Assert.error();
- return null;
- }
+ private Type mapTypeArgument(Type site, Type declaredBound, Type t, ProjectionKind pkind) {
+ return t.containsAny(vars) ?
+ t.map(new TypeArgumentProjection(site, declaredBound), pkind) :
+ t;
}
- private Type mapTypeArgument(Type t, ProjectionKind pkind) {
- if (!t.containsAny(vars)) {
- return t;
- } else if (!t.hasTag(WILDCARD) && pkind == ProjectionKind.DOWNWARDS) {
- //not defined
- return syms.botType;
- } else {
- Type upper = t.map(this, pkind);
- Type lower = t.map(this, pkind.complement());
- return makeWildcard(upper, lower);
+ class TypeArgumentProjection extends TypeMapping<ProjectionKind> {
+
+ Type site;
+ Type declaredBound;
+
+ TypeArgumentProjection(Type site, Type declaredBound) {
+ this.site = site;
+ this.declaredBound = declaredBound;
+ }
+
+ @Override
+ public Type visitType(Type t, ProjectionKind pkind) {
+ //type argument is some type containing restricted vars
+ if (pkind == ProjectionKind.DOWNWARDS) {
+ //not defined
+ return syms.botType;
+ }
+ Type upper = t.map(TypeProjection.this, ProjectionKind.UPWARDS);
+ Type lower = t.map(TypeProjection.this, ProjectionKind.DOWNWARDS);
+ List<Type> formals = site.tsym.type.getTypeArguments();
+ BoundKind bk;
+ Type bound;
+ if (!isSameType(upper, syms.objectType) &&
+ (declaredBound.containsAny(formals) ||
+ !isSubtype(declaredBound, upper))) {
+ bound = upper;
+ bk = EXTENDS;
+ } else if (!lower.hasTag(BOT)) {
+ bound = lower;
+ bk = SUPER;
+ } else {
+ bound = syms.objectType;
+ bk = UNBOUND;
+ }
+ return makeWildcard(bound, bk);
+ }
+
+ @Override
+ public Type visitWildcardType(WildcardType wt, ProjectionKind pkind) {
+ //type argument is some wildcard whose bound contains restricted vars
+ Type bound = syms.botType;
+ BoundKind bk = wt.kind;
+ switch (wt.kind) {
+ case EXTENDS:
+ bound = wt.type.map(TypeProjection.this, pkind);
+ if (bound.hasTag(BOT)) {
+ return syms.botType;
+ }
+ break;
+ case SUPER:
+ bound = wt.type.map(TypeProjection.this, pkind.complement());
+ if (bound.hasTag(BOT)) {
+ bound = syms.objectType;
+ bk = UNBOUND;
+ }
+ break;
+ }
+ return makeWildcard(bound, bk);
+ }
+
+ private Type makeWildcard(Type bound, BoundKind bk) {
+ return new WildcardType(bound, bk, syms.boundClass) {
+ @Override
+ protected boolean needsStripping() {
+ return true;
+ }
+ };
}
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java Wed Nov 29 22:40:23 2017 +0100
@@ -63,6 +63,7 @@
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
+import com.sun.tools.javac.util.Position;
import java.util.EnumSet;
import java.util.HashMap;
@@ -305,7 +306,7 @@
JCMethodDecl md = (JCMethodDecl)decls(oldTree.def).head;
List<JCVariableDecl> params = md.params;
JCBlock body = md.body;
- JCLambda newTree = make.Lambda(params, body);
+ JCLambda newTree = make.at(oldTree).Lambda(params, body);
return List.of(newTree);
}
@@ -418,7 +419,7 @@
List<JCEnhancedForLoop> rewrite(JCEnhancedForLoop oldTree) {
JCEnhancedForLoop newTree = copier.copy(oldTree);
newTree.var = rewriteVarType(oldTree.var);
- newTree.body = make.Block(0, List.nil());
+ newTree.body = make.at(oldTree.body).Block(0, List.nil());
return List.of(newTree);
}
@Override
@@ -551,7 +552,8 @@
JCStatement treeToAnalyze = (JCStatement)rewriting.originalTree;
if (rewriting.env.info.scope.owner.kind == Kind.TYP) {
//add a block to hoist potential dangling variable declarations
- treeToAnalyze = make.Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
+ treeToAnalyze = make.at(Position.NOPOS)
+ .Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
}
//TODO: to further refine the analysis, try all rewriting combinations
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java Wed Nov 29 22:40:23 2017 +0100
@@ -57,6 +57,7 @@
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DiagnosticSource;
+import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
@@ -98,6 +99,7 @@
protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>();
private final DeferredAttr deferredAttr;
+ private final JCDiagnostic.Factory diags;
private final Attr attr;
private final Symtab syms;
private final Log log;
@@ -121,6 +123,7 @@
protected ArgumentAttr(Context context) {
context.put(methodAttrKey, this);
deferredAttr = DeferredAttr.instance(context);
+ diags = JCDiagnostic.Factory.instance(context);
attr = Attr.instance(context);
syms = Symtab.instance(context);
log = Log.instance(context);
@@ -482,18 +485,14 @@
List<JCReturn> returnExpressions() {
return returnExpressions.orElseGet(() -> {
final List<JCReturn> res;
- if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION) {
- res = List.of(attr.make.Return((JCExpression)speculativeTree.body));
- } else {
- ListBuffer<JCReturn> returnExpressions = new ListBuffer<>();
- new LambdaReturnScanner() {
- @Override
- public void visitReturn(JCReturn tree) {
- returnExpressions.add(tree);
- }
- }.scan(speculativeTree.body);
- res = returnExpressions.toList();
- }
+ ListBuffer<JCReturn> buf = new ListBuffer<>();
+ new LambdaReturnScanner() {
+ @Override
+ public void visitReturn(JCReturn tree) {
+ buf.add(tree);
+ }
+ }.scan(speculativeTree.body);
+ res = buf.toList();
returnExpressions = Optional.of(res);
return res;
});
@@ -519,16 +518,38 @@
private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) {
CheckContext checkContext = resultInfo.checkContext;
ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo);
- for (JCReturn ret : returnExpressions()) {
- Type t = getReturnType(ret);
- if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION || !t.hasTag(VOID)) {
- checkSpeculative(ret.expr, t, bodyResultInfo);
- }
+ switch (speculativeTree.getBodyKind()) {
+ case EXPRESSION:
+ checkSpeculative(speculativeTree.body, speculativeTree.body.type, bodyResultInfo);
+ break;
+ case STATEMENT:
+ for (JCReturn ret : returnExpressions()) {
+ checkReturnInStatementLambda(ret, bodyResultInfo);
+ }
+ break;
}
attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext);
}
+ /**
+ * This is an inlined version of {@link Attr#visitReturn(JCReturn)}.
+ */
+ void checkReturnInStatementLambda(JCReturn ret, ResultInfo resultInfo) {
+ if (resultInfo.pt.hasTag(VOID) && ret.expr != null) {
+ //fail - if the function type's result is void, the lambda body must be a void-compatible block.
+ resultInfo.checkContext.report(speculativeTree.pos(),
+ diags.fragment("unexpected.ret.val"));
+ } else if (!resultInfo.pt.hasTag(VOID)) {
+ if (ret.expr == null) {
+ //fail - if the function type's result is non-void, the lambda body must be a value-compatible block.
+ resultInfo.checkContext.report(speculativeTree.pos(),
+ diags.fragment("missing.ret.val"));
+ }
+ checkSpeculative(ret.expr, ret.expr.type, resultInfo);
+ }
+ }
+
/** Get the type associated with given return expression. */
Type getReturnType(JCReturn ret) {
if (ret.expr == null) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Nov 29 22:40:23 2017 +0100
@@ -946,8 +946,6 @@
}
Type checkLocalVarType(DiagnosticPosition pos, Type t, Name name) {
- //upward project the initializer type
- t = types.upward(t, types.captures(t));
//check that resulting type is not the null type
if (t.hasTag(BOT)) {
log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferNull));
@@ -956,7 +954,9 @@
log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferVoid));
return types.createErrorType(t);
}
- return t;
+
+ //upward project the initializer type
+ return types.upward(t, types.captures(t));
}
Type checkMethod(final Type mtype,
@@ -3557,18 +3557,19 @@
Scope staticallyImportedSoFar, Scope topLevelScope,
Symbol sym, boolean staticImport) {
Filter<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous();
- Symbol clashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
- if (clashing == null && !staticImport) {
- clashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
+ Symbol ordinaryClashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
+ Symbol staticClashing = null;
+ if (ordinaryClashing == null && !staticImport) {
+ staticClashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
}
- if (clashing != null) {
- if (staticImport)
- log.error(pos, Errors.AlreadyDefinedStaticSingleImport(clashing));
+ if (ordinaryClashing != null || staticClashing != null) {
+ if (ordinaryClashing != null)
+ log.error(pos, Errors.AlreadyDefinedSingleImport(ordinaryClashing));
else
- log.error(pos, Errors.AlreadyDefinedSingleImport(clashing));
+ log.error(pos, Errors.AlreadyDefinedStaticSingleImport(staticClashing));
return false;
}
- clashing = topLevelScope.findFirst(sym.name, duplicates);
+ Symbol clashing = topLevelScope.findFirst(sym.name, duplicates);
if (clashing != null) {
log.error(pos, Errors.AlreadyDefinedThisUnit(clashing));
return false;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java Wed Nov 29 22:40:23 2017 +0100
@@ -91,6 +91,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.Namespace;
import jdk.dynalink.Operation;
@@ -189,85 +190,126 @@
assertParameterCount(callSiteDescriptor, isFixedKey ? 1 : 2);
final LinkerServices linkerServices = req.linkerServices;
final MethodType callSiteType = callSiteDescriptor.getMethodType();
- final Class<?> declaredType = callSiteType.parameterType(0);
final GuardedInvocationComponent nextComponent = getNextComponent(req);
+ final GuardedInvocationComponentAndCollectionType gicact = guardedInvocationComponentAndCollectionType(
+ callSiteType, linkerServices, MethodHandles::arrayElementGetter, GET_LIST_ELEMENT, GET_MAP_ELEMENT);
+
+ if (gicact == null) {
+ // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
+ return nextComponent;
+ }
+
+ final Object typedName = getTypedName(name, gicact.collectionType == CollectionType.MAP, linkerServices);
+ if (typedName == INVALID_NAME) {
+ return nextComponent;
+ }
+
+ return guardComponentWithRangeCheck(gicact, linkerServices,
+ callSiteDescriptor, nextComponent, new Binder(linkerServices, callSiteType, typedName),
+ isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2);
+ }
+
+ private static class GuardedInvocationComponentAndCollectionType {
+ final GuardedInvocationComponent gic;
+ final CollectionType collectionType;
+
+ GuardedInvocationComponentAndCollectionType(final GuardedInvocationComponent gic, final CollectionType collectionType) {
+ this.gic = gic;
+ this.collectionType = collectionType;
+ }
+ }
+
+ private GuardedInvocationComponentAndCollectionType guardedInvocationComponentAndCollectionType(
+ final MethodType callSiteType, final LinkerServices linkerServices,
+ final Function<Class<?>, MethodHandle> arrayMethod, final MethodHandle listMethod, final MethodHandle mapMethod) {
+ final Class<?> declaredType = callSiteType.parameterType(0);
// If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
// is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
// dealing with an array, or a list or map, but hey...
// Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
// in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
- final GuardedInvocationComponent gic;
- final CollectionType collectionType;
if(declaredType.isArray()) {
- gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
- collectionType = CollectionType.ARRAY;
+ return new GuardedInvocationComponentAndCollectionType(
+ createInternalFilteredGuardedInvocationComponent(arrayMethod.apply(declaredType), linkerServices),
+ CollectionType.ARRAY);
} else if(List.class.isAssignableFrom(declaredType)) {
- gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
- collectionType = CollectionType.LIST;
+ return new GuardedInvocationComponentAndCollectionType(
+ createInternalFilteredGuardedInvocationComponent(listMethod, linkerServices),
+ CollectionType.LIST);
} else if(Map.class.isAssignableFrom(declaredType)) {
- gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
- collectionType = CollectionType.MAP;
+ return new GuardedInvocationComponentAndCollectionType(
+ createInternalFilteredGuardedInvocationComponent(mapMethod, linkerServices),
+ CollectionType.MAP);
} else if(clazz.isArray()) {
- gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
- collectionType = CollectionType.ARRAY;
+ return new GuardedInvocationComponentAndCollectionType(
+ getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(arrayMethod.apply(clazz)), callSiteType),
+ CollectionType.ARRAY);
} else if(List.class.isAssignableFrom(clazz)) {
- gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
- linkerServices);
- collectionType = CollectionType.LIST;
+ return new GuardedInvocationComponentAndCollectionType(
+ createInternalFilteredGuardedInvocationComponent(listMethod, Guards.asType(LIST_GUARD, callSiteType),
+ List.class, ValidationType.INSTANCE_OF, linkerServices),
+ CollectionType.LIST);
} else if(Map.class.isAssignableFrom(clazz)) {
- gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
- linkerServices);
- collectionType = CollectionType.MAP;
- } else {
- // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
- return nextComponent;
+ return new GuardedInvocationComponentAndCollectionType(
+ createInternalFilteredGuardedInvocationComponent(mapMethod, Guards.asType(MAP_GUARD, callSiteType),
+ Map.class, ValidationType.INSTANCE_OF, linkerServices),
+ CollectionType.MAP);
}
+ return null;
+ }
+ private static final Object INVALID_NAME = new Object();
+
+ private static Object getTypedName(final Object name, final boolean isMap, final LinkerServices linkerServices) throws Exception {
// Convert the key to a number if we're working with a list or array
- final Object typedName;
- if (collectionType != CollectionType.MAP && isFixedKey) {
+ if (!isMap && name != null) {
final Integer integer = convertKeyToInteger(name, linkerServices);
if (integer == null || integer.intValue() < 0) {
// key is not a non-negative integer, it can never address an
// array or list element
- return nextComponent;
+ return INVALID_NAME;
}
- typedName = integer;
- } else {
- typedName = name;
+ return integer;
}
+ return name;
+ }
- final GuardedInvocation gi = gic.getGuardedInvocation();
- final Binder binder = new Binder(linkerServices, callSiteType, typedName);
- final MethodHandle invocation = gi.getInvocation();
+ private static GuardedInvocationComponent guardComponentWithRangeCheck(
+ final GuardedInvocationComponentAndCollectionType gicact, final LinkerServices linkerServices,
+ final CallSiteDescriptor callSiteDescriptor, final GuardedInvocationComponent nextComponent, final Binder binder,
+ final MethodHandle noOp) {
+ final MethodType callSiteType = callSiteDescriptor.getMethodType();
final MethodHandle checkGuard;
- switch(collectionType) {
- case LIST:
- checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
- break;
- case MAP:
- checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
- break;
- case ARRAY:
- checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
- break;
- default:
- throw new AssertionError();
+ switch(gicact.collectionType) {
+ case LIST:
+ checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
+ break;
+ case MAP:
+ checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
+ break;
+ case ARRAY:
+ checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
+ break;
+ default:
+ throw new AssertionError();
}
- // If there's no next component, produce a fixed null-returning one
+ // If there's no next component, produce a fixed no-op one
final GuardedInvocationComponent finalNextComponent;
if (nextComponent != null) {
finalNextComponent = nextComponent;
} else {
- final MethodHandle nullGetterHandle = isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2;
- finalNextComponent = createGuardedInvocationComponentAsType(nullGetterHandle, callSiteType, linkerServices);
+ finalNextComponent = createGuardedInvocationComponentAsType(noOp, callSiteType, linkerServices);
}
- final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+ final GuardedInvocationComponent gic = gicact.gic;
+ final GuardedInvocation gi = gic.getGuardedInvocation();
+
+ final MethodPair matchedInvocations = matchReturnTypes(binder.bind(gi.getInvocation()),
finalNextComponent.getGuardedInvocation().getInvocation());
+
return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
@@ -435,90 +477,37 @@
assertParameterCount(callSiteDescriptor, isFixedKey ? 2 : 3);
final LinkerServices linkerServices = req.linkerServices;
final MethodType callSiteType = callSiteDescriptor.getMethodType();
- final Class<?> declaredType = callSiteType.parameterType(0);
+
+ final GuardedInvocationComponentAndCollectionType gicact = guardedInvocationComponentAndCollectionType(
+ callSiteType, linkerServices, MethodHandles::arrayElementSetter, SET_LIST_ELEMENT, PUT_MAP_ELEMENT);
- final GuardedInvocationComponent gic;
- // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
- // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
- // dealing with an array, or a list or map, but hey...
- // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
- // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
- final CollectionType collectionType;
- if(declaredType.isArray()) {
- gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices);
- collectionType = CollectionType.ARRAY;
- } else if(List.class.isAssignableFrom(declaredType)) {
- gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices);
- collectionType = CollectionType.LIST;
- } else if(Map.class.isAssignableFrom(declaredType)) {
- gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices);
- collectionType = CollectionType.MAP;
- } else if(clazz.isArray()) {
- gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(
- MethodHandles.arrayElementSetter(clazz)), callSiteType);
- collectionType = CollectionType.ARRAY;
- } else if(List.class.isAssignableFrom(clazz)) {
- gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
- linkerServices);
- collectionType = CollectionType.LIST;
- } else if(Map.class.isAssignableFrom(clazz)) {
- gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType),
- Map.class, ValidationType.INSTANCE_OF, linkerServices);
- collectionType = CollectionType.MAP;
- } else {
- // Can't set elements for objects that are neither arrays, nor list, nor maps.
- gic = null;
- collectionType = null;
+ if(gicact == null) {
+ return getNextComponent(req);
}
+ final boolean isMap = gicact.collectionType == CollectionType.MAP;
+
// In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
// as maps will always succeed in setting the element and will never need to fall back to the next component
// operation.
- final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getNextComponent(req);
- if(gic == null) {
+ final GuardedInvocationComponent nextComponent = isMap ? null : getNextComponent(req);
+
+ final Object typedName = getTypedName(name, isMap, linkerServices);
+ if (typedName == INVALID_NAME) {
return nextComponent;
}
- // Convert the key to a number if we're working with a list or array
- final Object typedName;
- if (collectionType != CollectionType.MAP && isFixedKey) {
- final Integer integer = convertKeyToInteger(name, linkerServices);
- if (integer == null || integer.intValue() < 0) {
- // key is not a non-negative integer, it can never address an
- // array or list element
- return nextComponent;
- }
- typedName = integer;
- } else {
- typedName = name;
- }
-
+ final GuardedInvocationComponent gic = gicact.gic;
final GuardedInvocation gi = gic.getGuardedInvocation();
final Binder binder = new Binder(linkerServices, callSiteType, typedName);
final MethodHandle invocation = gi.getInvocation();
- if (collectionType == CollectionType.MAP) {
- assert nextComponent == null;
+ if (isMap) {
return gic.replaceInvocation(binder.bind(invocation));
}
- assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY;
- final MethodHandle checkGuard = convertArgToNumber(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST :
- RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
-
- // If there's no next component, produce a no-op one.
- final GuardedInvocationComponent finalNextComponent;
- if (nextComponent != null) {
- finalNextComponent = nextComponent;
- } else {
- final MethodHandle noOpSetterHandle = isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3;
- finalNextComponent = createGuardedInvocationComponentAsType(noOpSetterHandle, callSiteType, linkerServices);
- }
-
- final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
- finalNextComponent.getGuardedInvocation().getInvocation());
- return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
- gic.getValidatorClass(), gic.getValidationType());
+ return guardComponentWithRangeCheck(gicact, linkerServices, callSiteDescriptor,
+ nextComponent, binder, isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3);
}
private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
--- a/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java Wed Nov 29 22:40:23 2017 +0100
@@ -43,7 +43,7 @@
* a class, it also contains information to (1) describe the public API;
* (2) compare the public API of this class with another class; (3) determine
* whether or not it's a nested class and, if so, the name of the associated
- * top level class; and (4) for an canonically ordered set of classes determine
+ * outer class; and (4) for an canonically ordered set of classes determine
* if the class versions are compatible. A set of classes is canonically
* ordered if the classes in the set have the same name, and the base class
* precedes the versioned classes and if each versioned class with version
@@ -53,10 +53,13 @@
final class FingerPrint {
private static final MessageDigest MD;
+ private final String basename;
+ private final String entryName;
+ private final int mrversion;
+
private final byte[] sha1;
private final ClassAttributes attrs;
private final boolean isClassEntry;
- private final String entryName;
static {
try {
@@ -67,16 +70,19 @@
}
}
- public FingerPrint(String entryName,byte[] bytes) throws IOException {
+ public FingerPrint(String basename, String entryName, int mrversion, byte[] bytes)
+ throws IOException {
+ this.basename = basename;
this.entryName = entryName;
- if (entryName.endsWith(".class") && isCafeBabe(bytes)) {
+ this.mrversion = mrversion;
+ if (isCafeBabe(bytes)) {
isClassEntry = true;
sha1 = sha1(bytes, 8); // skip magic number and major/minor version
attrs = getClassAttributes(bytes);
} else {
isClassEntry = false;
- sha1 = sha1(bytes);
- attrs = new ClassAttributes(); // empty class
+ sha1 = null;
+ attrs = null;
}
}
@@ -107,14 +113,24 @@
return attrs.equals(that.attrs);
}
- public String name() {
- String name = attrs.name;
- return name == null ? entryName : name;
+ public String basename() {
+ return basename;
+ }
+
+ public String entryName() {
+ return entryName;
}
- public String topLevelName() {
- String name = attrs.topLevelName;
- return name == null ? name() : name;
+ public String className() {
+ return attrs.name;
+ }
+
+ public int mrversion() {
+ return mrversion;
+ }
+
+ public String outerClassName() {
+ return attrs.outerClassName;
}
private byte[] sha1(byte[] entry) {
@@ -218,7 +234,7 @@
private static final class ClassAttributes extends ClassVisitor {
private String name;
- private String topLevelName;
+ private String outerClassName;
private String superName;
private int version;
private int access;
@@ -228,7 +244,7 @@
private final Set<Method> methods = new HashSet<>();
public ClassAttributes() {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
}
private boolean isPublic(int access) {
@@ -250,7 +266,7 @@
@Override
public void visitOuterClass(String owner, String name, String desc) {
if (!this.nestedClass) return;
- this.topLevelName = owner;
+ this.outerClassName = owner;
}
@Override
@@ -259,7 +275,7 @@
if (!this.nestedClass) return;
if (outerName == null) return;
if (!this.name.equals(name)) return;
- if (this.topLevelName == null) this.topLevelName = outerName;
+ if (this.outerClassName == null) this.outerClassName = outerName;
}
@Override
@@ -294,7 +310,7 @@
@Override
public void visitEnd() {
- this.nestedClass = this.topLevelName != null;
+ this.nestedClass = this.outerClassName != null;
}
@Override
--- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Wed Nov 29 22:40:23 2017 +0100
@@ -71,7 +71,6 @@
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-import static sun.tools.jar.Validator.ENTRYNAME_COMPARATOR;
/**
* This class implements a simple utility for creating files in the JAR
@@ -444,8 +443,8 @@
private void validateAndClose(File tmpfile) throws IOException {
if (ok && isMultiRelease) {
- try (JarFile jf = new JarFile(tmpfile)) {
- ok = Validator.validate(this, jf);
+ try (ZipFile zf = new ZipFile(tmpfile)) {
+ ok = Validator.validate(this, zf);
if (!ok) {
error(formatMsg("error.validator.jarfile.invalid", fname));
}
@@ -1784,7 +1783,7 @@
private boolean describeModule(ZipFile zipFile) throws IOException {
ZipFileModuleInfoEntry[] infos = zipFile.stream()
.filter(e -> isModuleInfoEntry(e.getName()))
- .sorted(Validator.ENTRY_COMPARATOR)
+ .sorted(ENTRY_COMPARATOR)
.map(e -> new ZipFileModuleInfoEntry(zipFile, e))
.toArray(ZipFileModuleInfoEntry[]::new);
@@ -2216,4 +2215,48 @@
return hashesBuilder.computeHashes(Set.of(name)).get(name);
}
}
+
+ // sort base entries before versioned entries, and sort entry classes with
+ // nested classes so that the outter class appears before the associated
+ // nested class
+ static Comparator<String> ENTRYNAME_COMPARATOR = (s1, s2) -> {
+
+ if (s1.equals(s2)) return 0;
+ boolean b1 = s1.startsWith(VERSIONS_DIR);
+ boolean b2 = s2.startsWith(VERSIONS_DIR);
+ if (b1 && !b2) return 1;
+ if (!b1 && b2) return -1;
+ int n = 0; // starting char for String compare
+ if (b1 && b2) {
+ // normally strings would be sorted so "10" goes before "9", but
+ // version number strings need to be sorted numerically
+ n = VERSIONS_DIR.length(); // skip the common prefix
+ int i1 = s1.indexOf('/', n);
+ int i2 = s2.indexOf('/', n);
+ if (i1 == -1) throw new Validator.InvalidJarException(s1);
+ if (i2 == -1) throw new Validator.InvalidJarException(s2);
+ // shorter version numbers go first
+ if (i1 != i2) return i1 - i2;
+ // otherwise, handle equal length numbers below
+ }
+ int l1 = s1.length();
+ int l2 = s2.length();
+ int lim = Math.min(l1, l2);
+ for (int k = n; k < lim; k++) {
+ char c1 = s1.charAt(k);
+ char c2 = s2.charAt(k);
+ if (c1 != c2) {
+ // change natural ordering so '.' comes before '$'
+ // i.e. outer classes come before nested classes
+ if (c1 == '$' && c2 == '.') return 1;
+ if (c1 == '.' && c2 == '$') return -1;
+ return c1 - c2;
+ }
+ }
+ return l1 - l2;
+ };
+
+ static Comparator<ZipEntry> ENTRY_COMPARATOR =
+ Comparator.comparing(ZipEntry::getName, ENTRYNAME_COMPARATOR);
+
}
--- a/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Wed Nov 29 22:40:23 2017 +0100
@@ -28,24 +28,22 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
-import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.function.Consumer;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
+import java.util.TreeMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static sun.tools.jar.Main.VERSIONS_DIR;
@@ -55,269 +53,184 @@
import static sun.tools.jar.Main.formatMsg;
import static sun.tools.jar.Main.formatMsg2;
import static sun.tools.jar.Main.toBinaryName;
-import static sun.tools.jar.Main.isModuleInfoEntry;
final class Validator {
- private final static boolean DEBUG = Boolean.getBoolean("jar.debug");
- private final Map<String,FingerPrint> fps = new HashMap<>();
+
+ private final Map<String,FingerPrint> classes = new HashMap<>();
private final Main main;
- private final JarFile jf;
- private int oldVersion = -1;
- private String currentTopLevelName;
+ private final ZipFile zf;
private boolean isValid = true;
private Set<String> concealedPkgs = Collections.emptySet();
private ModuleDescriptor md;
private String mdName;
- private Validator(Main main, JarFile jf) {
+ private Validator(Main main, ZipFile zf) {
this.main = main;
- this.jf = jf;
+ this.zf = zf;
checkModuleDescriptor(MODULE_INFO);
}
- static boolean validate(Main main, JarFile jf) throws IOException {
- return new Validator(main, jf).validate();
+ static boolean validate(Main main, ZipFile zf) throws IOException {
+ return new Validator(main, zf).validate();
}
private boolean validate() {
try {
- jf.stream()
- .filter(e -> !e.isDirectory() &&
- !e.getName().equals(MANIFEST_NAME))
- .sorted(ENTRY_COMPARATOR)
- .forEachOrdered(e -> validate(e));
- return isValid;
+ zf.stream()
+ .filter(e -> e.getName().endsWith(".class"))
+ .map(this::getFingerPrint)
+ .filter(FingerPrint::isClass) // skip any non-class entry
+ .collect(Collectors.groupingBy(
+ FingerPrint::mrversion,
+ TreeMap::new,
+ Collectors.toMap(FingerPrint::className,
+ Function.identity(),
+ this::sameNameFingerPrint)))
+ .forEach((version, entries) -> {
+ if (version == 0)
+ validateBase(entries);
+ else
+ validateVersioned(entries);
+ });
} catch (InvalidJarException e) {
- error(formatMsg("error.validator.bad.entry.name", e.getMessage()));
+ errorAndInvalid(e.getMessage());
}
- return false;
+ return isValid;
}
- private static class InvalidJarException extends RuntimeException {
+ static class InvalidJarException extends RuntimeException {
private static final long serialVersionUID = -3642329147299217726L;
InvalidJarException(String msg) {
super(msg);
}
}
- // sort base entries before versioned entries, and sort entry classes with
- // nested classes so that the top level class appears before the associated
- // nested class
- static Comparator<String> ENTRYNAME_COMPARATOR = (s1, s2) -> {
+ private FingerPrint sameNameFingerPrint(FingerPrint fp1, FingerPrint fp2) {
+ checkClassName(fp1);
+ checkClassName(fp2);
+ // entries/classes with same name, return fp2 for now ?
+ return fp2;
+ }
+
+ private FingerPrint getFingerPrint(ZipEntry ze) {
+ // figure out the version and basename from the ZipEntry
+ String ename = ze.getName();
+ String bname = ename;
+ int version = 0;
- if (s1.equals(s2)) return 0;
- boolean b1 = s1.startsWith(VERSIONS_DIR);
- boolean b2 = s2.startsWith(VERSIONS_DIR);
- if (b1 && !b2) return 1;
- if (!b1 && b2) return -1;
- int n = 0; // starting char for String compare
- if (b1 && b2) {
- // normally strings would be sorted so "10" goes before "9", but
- // version number strings need to be sorted numerically
- n = VERSIONS_DIR.length(); // skip the common prefix
- int i1 = s1.indexOf('/', n);
- int i2 = s2.indexOf('/', n);
- if (i1 == -1) throw new InvalidJarException(s1);
- if (i2 == -1) throw new InvalidJarException(s2);
- // shorter version numbers go first
- if (i1 != i2) return i1 - i2;
- // otherwise, handle equal length numbers below
+ if (ename.startsWith(VERSIONS_DIR)) {
+ int n = ename.indexOf("/", VERSIONS_DIR_LENGTH);
+ if (n == -1) {
+ throw new InvalidJarException(
+ formatMsg("error.validator.version.notnumber", ename));
+ }
+ try {
+ version = Integer.parseInt(ename, VERSIONS_DIR_LENGTH, n, 10);
+ } catch (NumberFormatException x) {
+ throw new InvalidJarException(
+ formatMsg("error.validator.version.notnumber", ename));
+ }
+ if (n == ename.length()) {
+ throw new InvalidJarException(
+ formatMsg("error.validator.entryname.tooshort", ename));
+ }
+ bname = ename.substring(n + 1);
}
- int l1 = s1.length();
- int l2 = s2.length();
- int lim = Math.min(l1, l2);
- for (int k = n; k < lim; k++) {
- char c1 = s1.charAt(k);
- char c2 = s2.charAt(k);
- if (c1 != c2) {
- // change natural ordering so '.' comes before '$'
- // i.e. top level classes come before nested classes
- if (c1 == '$' && c2 == '.') return 1;
- if (c1 == '.' && c2 == '$') return -1;
- return c1 - c2;
- }
+
+ // return the cooresponding fingerprint entry
+ try (InputStream is = zf.getInputStream(ze)) {
+ return new FingerPrint(bname, ename, version, is.readAllBytes());
+ } catch (IOException x) {
+ throw new InvalidJarException(x.getMessage());
}
- return l1 - l2;
- };
-
- static Comparator<ZipEntry> ENTRY_COMPARATOR =
- Comparator.comparing(ZipEntry::getName, ENTRYNAME_COMPARATOR);
+ }
/*
- * Validator has state and assumes entries provided to accept are ordered
- * from base entries first and then through the versioned entries in
- * ascending version order. Also, to find isolated nested classes,
- * classes must be ordered so that the top level class is before the associated
- * nested class(es).
- */
- public void validate(JarEntry je) {
- String entryName = je.getName();
-
- // directories are always accepted
- if (entryName.endsWith("/")) {
- debug("%s is a directory", entryName);
- return;
- }
-
- // validate the versioned module-info
- if (isModuleInfoEntry(entryName)) {
- if (!entryName.equals(mdName))
- checkModuleDescriptor(entryName);
- return;
- }
-
- // figure out the version and basename from the JarEntry
- int version;
- String basename;
- String versionStr = null;;
- if (entryName.startsWith(VERSIONS_DIR)) {
- int n = entryName.indexOf("/", VERSIONS_DIR_LENGTH);
- if (n == -1) {
- error(formatMsg("error.validator.version.notnumber", entryName));
+ * Validates (a) if there is any isolated nested class, and (b) if the
+ * class name in class file (by asm) matches the entry's basename.
+ */
+ public void validateBase(Map<String, FingerPrint> fps) {
+ fps.values().forEach( fp -> {
+ if (!checkClassName(fp)) {
isValid = false;
return;
}
- versionStr = entryName.substring(VERSIONS_DIR_LENGTH, n);
- try {
- version = Integer.parseInt(versionStr);
- } catch (NumberFormatException x) {
- error(formatMsg("error.validator.version.notnumber", entryName));
- isValid = false;
- return;
+ if (fp.isNestedClass()) {
+ if (!checkNestedClass(fp, fps)) {
+ isValid = false;
+ }
}
- if (n == entryName.length()) {
- error(formatMsg("error.validator.entryname.tooshort", entryName));
- isValid = false;
+ classes.put(fp.className(), fp);
+ });
+ }
+
+ public void validateVersioned(Map<String, FingerPrint> fps) {
+
+ fps.values().forEach( fp -> {
+
+ // validate the versioned module-info
+ if (MODULE_INFO.equals(fp.basename())) {
+ checkModuleDescriptor(fp.entryName());
return;
}
- basename = entryName.substring(n + 1);
- } else {
- version = 0;
- basename = entryName;
- }
- debug("\n===================\nversion %d %s", version, entryName);
-
- if (oldVersion != version) {
- oldVersion = version;
- currentTopLevelName = null;
- if (md == null && versionStr != null) {
- // don't have a base module-info.class yet, try to see if
- // a versioned one exists
- checkModuleDescriptor(VERSIONS_DIR + versionStr + "/" + MODULE_INFO);
- }
- }
-
- // analyze the entry, keeping key attributes
- FingerPrint fp;
- try (InputStream is = jf.getInputStream(je)) {
- fp = new FingerPrint(basename, is.readAllBytes());
- } catch (IOException x) {
- error(x.getMessage());
- isValid = false;
- return;
- }
- String internalName = fp.name();
-
- // process a base entry paying attention to nested classes
- if (version == 0) {
- debug("base entry found");
- if (fp.isNestedClass()) {
- debug("nested class found");
- if (fp.topLevelName().equals(currentTopLevelName)) {
- fps.put(internalName, fp);
- return;
- }
- error(formatMsg("error.validator.isolated.nested.class", entryName));
- isValid = false;
- return;
- }
- // top level class or resource entry
- if (fp.isClass()) {
- currentTopLevelName = fp.topLevelName();
- if (!checkInternalName(entryName, basename, internalName)) {
- isValid = false;
- return;
- }
- }
- fps.put(internalName, fp);
- return;
- }
-
- // process a versioned entry, look for previous entry with same name
- FingerPrint matchFp = fps.get(internalName);
- debug("looking for match");
- if (matchFp == null) {
- debug("no match found");
- if (fp.isClass()) {
+ // process a versioned entry, look for previous entry with same name
+ FingerPrint matchFp = classes.get(fp.className());
+ if (matchFp == null) {
+ // no match found
if (fp.isNestedClass()) {
- if (!checkNestedClass(version, entryName, internalName, fp)) {
+ if (!checkNestedClass(fp, fps)) {
isValid = false;
}
return;
}
if (fp.isPublicClass()) {
- if (!isConcealed(internalName)) {
- error(Main.formatMsg("error.validator.new.public.class", entryName));
- isValid = false;
+ if (!isConcealed(fp.className())) {
+ errorAndInvalid(formatMsg("error.validator.new.public.class",
+ fp.entryName()));
return;
- }
- warn(formatMsg("warn.validator.concealed.public.class", entryName));
- debug("%s is a public class entry in a concealed package", entryName);
+ }
+ // entry is a public class entry in a concealed package
+ warn(formatMsg("warn.validator.concealed.public.class",
+ fp.entryName()));
}
- debug("%s is a non-public class entry", entryName);
- fps.put(internalName, fp);
- currentTopLevelName = fp.topLevelName();
+ classes.put(fp.className(), fp);
return;
}
- debug("%s is a resource entry");
- fps.put(internalName, fp);
- return;
- }
- debug("match found");
- // are the two classes/resources identical?
- if (fp.isIdentical(matchFp)) {
- warn(formatMsg("warn.validator.identical.entry", entryName));
- return; // it's okay, just takes up room
- }
- debug("sha1 not equal -- different bytes");
+ // are the two classes/resources identical?
+ if (fp.isIdentical(matchFp)) {
+ warn(formatMsg("warn.validator.identical.entry", fp.entryName()));
+ return; // it's okay, just takes up room
+ }
- // ok, not identical, check for compatible class version and api
- if (fp.isClass()) {
+ // ok, not identical, check for compatible class version and api
if (fp.isNestedClass()) {
- if (!checkNestedClass(version, entryName, internalName, fp)) {
+ if (!checkNestedClass(fp, fps)) {
isValid = false;
}
+ return; // fall through, need check nested public class??
+ }
+ if (!fp.isCompatibleVersion(matchFp)) {
+ errorAndInvalid(formatMsg("error.validator.incompatible.class.version",
+ fp.entryName()));
return;
}
- debug("%s is a class entry", entryName);
- if (!fp.isCompatibleVersion(matchFp)) {
- error(formatMsg("error.validator.incompatible.class.version", entryName));
+ if (!fp.isSameAPI(matchFp)) {
+ errorAndInvalid(formatMsg("error.validator.different.api",
+ fp.entryName()));
+ return;
+ }
+ if (!checkClassName(fp)) {
isValid = false;
return;
}
- if (!fp.isSameAPI(matchFp)) {
- error(formatMsg("error.validator.different.api", entryName));
- isValid = false;
- return;
- }
- if (!checkInternalName(entryName, basename, internalName)) {
- isValid = false;
- return;
- }
- debug("fingerprints same -- same api");
- fps.put(internalName, fp);
- currentTopLevelName = fp.topLevelName();
+ classes.put(fp.className(), fp);
+
return;
- }
- debug("%s is a resource", entryName);
-
- warn(formatMsg("warn.validator.resources.with.same.name", entryName));
- fps.put(internalName, fp);
- return;
+ });
}
- /**
+ /*
* Checks whether or not the given versioned module descriptor's attributes
* are valid when compared against the root/base module descriptor.
*
@@ -326,12 +239,12 @@
* - A versioned descriptor can have different non-public `requires`
* clauses of platform ( `java.*` and `jdk.*` ) modules, and
* - A versioned descriptor can have different `uses` clauses, even of
- * service types defined outside of the platform modules.
+ * service types defined outside of the platform modules.
*/
private void checkModuleDescriptor(String miName) {
- ZipEntry je = jf.getEntry(miName);
- if (je != null) {
- try (InputStream jis = jf.getInputStream(je)) {
+ ZipEntry ze = zf.getEntry(miName);
+ if (ze != null) {
+ try (InputStream jis = zf.getInputStream(ze)) {
ModuleDescriptor md = ModuleDescriptor.read(jis);
// Initialize the base md if it's not yet. A "base" md can be either the
// root module-info.class or the first versioned module-info.class
@@ -344,7 +257,7 @@
// must have the implementation class of the services it 'provides'.
if (md.provides().stream().map(Provides::providers)
.flatMap(List::stream)
- .filter(p -> jf.getEntry(toBinaryName(p)) == null)
+ .filter(p -> zf.getEntry(toBinaryName(p)) == null)
.peek(p -> error(formatMsg("error.missing.provider", p)))
.count() != 0) {
isValid = false;
@@ -356,8 +269,7 @@
}
if (!base.name().equals(md.name())) {
- error(getMsg("error.validator.info.name.notequal"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.name.notequal"));
}
if (!base.requires().equals(md.requires())) {
Set<Requires> baseRequires = base.requires();
@@ -365,11 +277,9 @@
if (baseRequires.contains(r))
continue;
if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) {
- error(getMsg("error.validator.info.requires.transitive"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.requires.transitive"));
} else if (!isPlatformModule(r.name())) {
- error(getMsg("error.validator.info.requires.added"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.requires.added"));
}
}
for (Requires r : baseRequires) {
@@ -377,87 +287,78 @@
if (mdRequires.contains(r))
continue;
if (!isPlatformModule(r.name())) {
- error(getMsg("error.validator.info.requires.dropped"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.requires.dropped"));
}
}
}
if (!base.exports().equals(md.exports())) {
- error(getMsg("error.validator.info.exports.notequal"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.exports.notequal"));
}
if (!base.opens().equals(md.opens())) {
- error(getMsg("error.validator.info.opens.notequal"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.opens.notequal"));
}
if (!base.provides().equals(md.provides())) {
- error(getMsg("error.validator.info.provides.notequal"));
- isValid = false;
+ errorAndInvalid(getMsg("error.validator.info.provides.notequal"));
}
if (!base.mainClass().equals(md.mainClass())) {
- error(formatMsg("error.validator.info.manclass.notequal", je.getName()));
- isValid = false;
+ errorAndInvalid(formatMsg("error.validator.info.manclass.notequal",
+ ze.getName()));
}
if (!base.version().equals(md.version())) {
- error(formatMsg("error.validator.info.version.notequal", je.getName()));
- isValid = false;
+ errorAndInvalid(formatMsg("error.validator.info.version.notequal",
+ ze.getName()));
}
} catch (Exception x) {
- error(x.getMessage() + " : " + miName);
- this.isValid = false;
+ errorAndInvalid(x.getMessage() + " : " + miName);
}
}
}
+ private boolean checkClassName(FingerPrint fp) {
+ if (fp.className().equals(className(fp.basename()))) {
+ return true;
+ }
+ error(formatMsg2("error.validator.names.mismatch",
+ fp.entryName(), fp.className().replace("/", ".")));
+ return false;
+ }
+
+ private boolean checkNestedClass(FingerPrint fp, Map<String, FingerPrint> outerClasses) {
+ if (outerClasses.containsKey(fp.outerClassName())) {
+ return true;
+ }
+ // outer class was not available
+ error(formatMsg("error.validator.isolated.nested.class", fp.entryName()));
+ return false;
+ }
+
+ private boolean isConcealed(String className) {
+ if (concealedPkgs.isEmpty()) {
+ return false;
+ }
+ int idx = className.lastIndexOf('/');
+ String pkgName = idx != -1 ? className.substring(0, idx).replace('/', '.') : "";
+ return concealedPkgs.contains(pkgName);
+ }
+
private static boolean isPlatformModule(String name) {
return name.startsWith("java.") || name.startsWith("jdk.");
}
- private boolean checkInternalName(String entryName, String basename, String internalName) {
- String className = className(basename);
- if (internalName.equals(className)) {
- return true;
- }
- error(formatMsg2("error.validator.names.mismatch",
- entryName, internalName.replace("/", ".")));
- return false;
- }
-
- private boolean checkNestedClass(int version, String entryName, String internalName, FingerPrint fp) {
- debug("%s is a nested class entry in top level class %s", entryName, fp.topLevelName());
- if (fp.topLevelName().equals(currentTopLevelName)) {
- debug("%s (top level class) was accepted", fp.topLevelName());
- fps.put(internalName, fp);
- return true;
- }
- debug("top level class was not accepted");
- error(formatMsg("error.validator.isolated.nested.class", entryName));
- return false;
- }
-
- private String className(String entryName) {
+ private static String className(String entryName) {
return entryName.endsWith(".class") ? entryName.substring(0, entryName.length() - 6) : null;
}
- private boolean isConcealed(String internalName) {
- if (concealedPkgs.isEmpty()) {
- return false;
- }
- int idx = internalName.lastIndexOf('/');
- String pkgName = idx != -1 ? internalName.substring(0, idx).replace('/', '.') : "";
- return concealedPkgs.contains(pkgName);
- }
-
- private void debug(String fmt, Object... args) {
- if (DEBUG) System.err.format(fmt, args);
- }
-
private void error(String msg) {
main.error(msg);
}
+ private void errorAndInvalid(String msg) {
+ main.error(msg);
+ isValid = false;
+ }
+
private void warn(String msg) {
main.warn(msg);
}
-
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css Wed Nov 29 22:40:23 2017 +0100
@@ -1,10 +1,16 @@
-/* Javadoc style sheet */
-/*
-Overall document style
-*/
+/*
+ * Javadoc style sheet
+ */
@import url('resources/fonts/dejavu.css');
+/*
+ * Styles for individual HTML elements.
+ *
+ * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular
+ * HTML element throughout the page.
+ */
+
body {
background-color:#ffffff;
color:#353833;
@@ -41,9 +47,6 @@
padding-top:129px;
margin-top:-129px;
}
-.searchTagResult:before, .searchTagResult:target {
- color:red;
-}
pre {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
@@ -91,9 +94,16 @@
sup {
font-size:8px;
}
+
/*
-Document title and Copyright styles
-*/
+ * Styles for HTML generated by javadoc.
+ *
+ * These are style classes that are used by the standard doclet to generate HTML documentation.
+ */
+
+/*
+ * Styles for document title and copyright.
+ */
.clear {
clear:both;
height:0px;
@@ -124,8 +134,8 @@
font-weight:bold;
}
/*
-Navigation bar styles
-*/
+ * Styles for navigation bar.
+ */
.bar {
background-color:#4D7A97;
color:#FFFFFF;
@@ -233,8 +243,8 @@
overflow:hidden;
}
/*
-Page header and footer styles
-*/
+ * Styles for page header and footer.
+ */
.header, .footer {
clear:both;
margin:0 20px;
@@ -277,8 +287,8 @@
font-size:13px;
}
/*
-Heading styles
-*/
+ * Styles for headings.
+ */
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
background-color:#dee3e9;
border:1px solid #d0d9e0;
@@ -299,8 +309,8 @@
padding:0px 0 20px 0;
}
/*
-Page layout container styles
-*/
+ * Styles for page layout containers.
+ */
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
clear:both;
padding:10px 20px;
@@ -346,8 +356,8 @@
display:inline;
}
/*
-List styles
-*/
+ * Styles for lists.
+ */
li.circle {
list-style:circle;
}
@@ -403,8 +413,8 @@
margin-bottom:1px;
}
/*
-Table styles
-*/
+ * Styles for tables.
+ */
.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary,
.requiresSummary, .packagesSummary, .providesSummary, .usesSummary {
width:100%;
@@ -529,7 +539,6 @@
position:relative;
background-color:#4D7A97;
float:left;
-
}
.rowColor th, .altColor th {
font-weight:normal;
@@ -601,8 +610,8 @@
background-color:#EEEEEF;
}
/*
-Content styles
-*/
+ * Styles for contents.
+ */
.description pre {
margin-top:0;
}
@@ -613,27 +622,22 @@
.docSummary {
padding:0;
}
-
ul.blockList ul.blockList ul.blockList li.blockList h3 {
font-style:normal;
}
-
div.block {
font-size:14px;
font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
}
-
td.colLast div {
padding-top:0px;
}
-
-
td.colLast a {
padding-bottom:3px;
}
/*
-Formatting effect styles
-*/
+ * Styles for formatting effect.
+ */
.sourceLineNo {
color:green;
padding:0 30px 0 0;
@@ -668,18 +672,16 @@
margin-right:10px;
display:inline-block;
}
-
div.block div.deprecationComment, div.block div.block span.emphasizedPhrase,
div.block div.block span.interfaceName {
font-style:normal;
}
-
div.contentContainer ul.blockList li.blockList h2 {
padding-bottom:0px;
}
/*
-IFRAME specific styles
-*/
+ * Styles for IFRAME.
+ */
.mainContainer {
margin:0 auto;
padding:0;
@@ -733,11 +735,14 @@
margin-bottom:30px;
}
/*
-HTML5 specific styles
-*/
+ * Styles specific to HTML5 elements.
+ */
main, nav, header, footer, section {
display:block;
}
+/*
+ * Styles for javadoc search.
+ */
.ui-autocomplete-category {
font-weight:bold;
font-size:15px;
@@ -802,7 +807,9 @@
font-style:italic;
font-size:12px;
}
-
+.searchTagResult:before, .searchTagResult:target {
+ color:red;
+}
.moduleGraph span {
display:none;
position:absolute;
@@ -838,20 +845,17 @@
margin-top: 10px;
margin-bottom: 10px;
}
-
table.borderless > caption,
table.plain > caption,
table.striped > caption {
font-weight: bold;
font-size: smaller;
}
-
table.borderless th, table.borderless td,
table.plain th, table.plain td,
table.striped th, table.striped td {
padding: 2px 5px;
}
-
table.borderless,
table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th,
table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td {
@@ -860,7 +864,6 @@
table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr {
background-color: transparent;
}
-
table.plain {
border-collapse: collapse;
border: 1px solid black;
@@ -872,7 +875,6 @@
table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td {
border: 1px solid black;
}
-
table.striped {
border-collapse: collapse;
border: 1px solid black;
--- a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Wed Nov 29 22:40:23 2017 +0100
@@ -59,7 +59,6 @@
import jdk.jshell.Snippet.SubKind;
import jdk.jshell.TaskFactory.AnalyzeTask;
import jdk.jshell.TaskFactory.BaseTask;
-import jdk.jshell.TaskFactory.CompileTask;
import jdk.jshell.TaskFactory.ParseTask;
import jdk.jshell.Wrap.CompoundWrap;
import jdk.jshell.Wrap.Range;
@@ -454,7 +453,7 @@
name = "$" + ++varNumber;
}
}
- guts = Wrap.tempVarWrap(compileSource, typeName, name);
+ guts = Wrap.tempVarWrap(compileSource, ei.accessibleTypeName, name);
Collection<String> declareReferences = null; //TODO
snip = new VarSnippet(state.keyMap.keyForVariable(name), userSource, guts,
name, SubKind.TEMP_VAR_EXPRESSION_SUBKIND, typeName, declareReferences, null);
--- a/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,8 @@
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
@@ -69,6 +71,7 @@
public static class ExpressionInfo {
ExpressionTree tree;
String typeName;
+ String accessibleTypeName;
String fullTypeName;
List<String> parameterTypes;
String enclosingInstanceType;
@@ -215,6 +218,63 @@
return null;
}
+ /**
+ * A type is accessible if it is public or if it is package-private and is a
+ * type defined in JShell. Additionally, all its type arguments must be
+ * accessible
+ *
+ * @param type the type to check for accessibility
+ * @return true if the type name can be referenced
+ */
+ private boolean isAccessible(Type type) {
+ Symbol.TypeSymbol tsym = type.asElement();
+ return ((tsym.flags() & Flags.PUBLIC) != 0 ||
+ ((tsym.flags() & Flags.PRIVATE) == 0 &&
+ Util.isInJShellClass(tsym.flatName().toString()))) &&
+ type.getTypeArguments().stream()
+ .allMatch(this::isAccessible);
+ }
+
+ /**
+ * Return the superclass.
+ *
+ * @param type the type
+ * @return the superclass, or Object on error
+ */
+ private Type supertype(Type type) {
+ Type sup = types.supertype(type);
+ if (sup == Type.noType || sup == null) {
+ return syms.objectType;
+ }
+ return sup;
+ }
+
+ /**
+ * Find an accessible supertype.
+ *
+ * @param type the type
+ * @return the type, if it is accessible, otherwise a superclass or
+ * interface which is
+ */
+ private Type findAccessibleSupertype(Type type) {
+ // Iterate up the superclasses, see if any are accessible
+ for (Type sup = type; !types.isSameType(sup, syms.objectType); sup = supertype(sup)) {
+ if (isAccessible(sup)) {
+ return sup;
+ }
+ }
+ // Failing superclasses, look through superclasses for accessible interfaces
+ for (Type sup = type; !types.isSameType(sup, syms.objectType); sup = supertype(sup)) {
+ for (Type itf : types.interfaces(sup)) {
+ if (isAccessible(itf)) {
+ return itf;
+ }
+ }
+ }
+ // Punt, return Object which is the supertype of everything
+ return syms.objectType;
+ }
+
private ExpressionInfo treeToInfo(TreePath tp) {
if (tp != null) {
Tree tree = tp.getLeaf();
@@ -234,10 +294,12 @@
case NULL:
ei.isNonVoid = true;
ei.typeName = OBJECT_TYPE_NAME;
+ ei.accessibleTypeName = OBJECT_TYPE_NAME;
break;
default: {
ei.isNonVoid = true;
ei.typeName = varTypeName(type, false);
+ ei.accessibleTypeName = varTypeName(findAccessibleSupertype(type), false);
ei.fullTypeName = varTypeName(type, true);
break;
}
--- a/src/jdk.jshell/share/classes/jdk/jshell/Util.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Util.java Wed Nov 29 22:40:23 2017 +0100
@@ -29,6 +29,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -82,6 +83,17 @@
return sb.toString();
}
+ /**
+ * Check if this is the name of something in JShell.
+ *
+ * @param s the name of the class, method, variable, ...
+ * @return true if it is, or is within a JShell defined wrapper class
+ */
+ static boolean isInJShellClass(String s) {
+ Matcher m = PREFIX_PATTERN.matcher(s);
+ return m.find() && m.start() == 0;
+ }
+
static String asLetters(int i) {
if (i == 0) {
return "";
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Wed Nov 29 22:40:23 2017 +0100
@@ -306,10 +306,10 @@
@Override
public boolean enterVarNode(final VarNode varNode) {
- if (!inSplitNode()) {
+ // ES6 block scoped declarations are already placed at their proper position by splitter
+ if (!inSplitNode() || varNode.isBlockScoped()) {
return super.enterVarNode(varNode);
}
- assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
final Expression init = varNode.getInit();
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Splitter.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Splitter.java Wed Nov 29 22:40:23 2017 +0100
@@ -41,6 +41,7 @@
import jdk.nashorn.internal.ir.SplitNode;
import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.VarNode;
import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -201,8 +202,9 @@
for (final Statement statement : block.getStatements()) {
final long weight = WeighNodes.weigh(statement, weightCache);
+ final boolean isBlockScopedVarNode = isBlockScopedVarNode(statement);
- if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) {
+ if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal() || isBlockScopedVarNode) {
if (!statements.isEmpty()) {
splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
statements = new ArrayList<>();
@@ -210,7 +212,7 @@
}
}
- if (statement.isTerminal()) {
+ if (statement.isTerminal() || isBlockScopedVarNode) {
splits.add(statement);
} else {
statements.add(statement);
@@ -243,6 +245,10 @@
return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT));
}
+ private boolean isBlockScopedVarNode(final Statement statement) {
+ return statement instanceof VarNode && ((VarNode) statement).isBlockScoped();
+ }
+
@Override
public boolean enterBlock(final Block block) {
if (block.isCatchBlock()) {
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitReturn.java Wed Nov 29 22:35:35 2017 +0100
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitReturn.java Wed Nov 29 22:40:23 2017 +0100
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.ir;
+import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
/**
@@ -37,6 +38,7 @@
private static final long serialVersionUID = 1L;
/** The sole instance of this AST node. */
+ @Ignore
public static final SplitReturn INSTANCE = new SplitReturn();
private SplitReturn() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/Component/GetScreenLocTest/ComponentGetLocationOnScreenNPETest.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8189204
+ * @summary Possible NPE in Component::getLocationOnScreen()
+ * @run main ComponentGetLocationOnScreenNPETest
+ */
+
+import javax.swing.*;
+import java.awt.*;
+
+public class ComponentGetLocationOnScreenNPETest {
+
+ private static Frame frame;
+ private static JPanel panel;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ frame = new Frame();
+ JPanel parentPanel = new JPanel() {
+ @Override
+ public Container getParent() {
+ return new Frame();
+ }
+ };
+ frame.add(parentPanel);
+ panel = new JPanel();
+ parentPanel.add(panel);
+ frame.setVisible(true);
+ });
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ robot.delay(200);
+
+ SwingUtilities.invokeAndWait(panel::getLocationOnScreen);
+ SwingUtilities.invokeLater(frame::dispose);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/dnd/RecognizedActionTest/RecognizedActionTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @key headful
+ * @bug 4494085 8158366
+ * @summary verifies that the recognized action matches modifiers state
+ * @compile RecognizedActionTest.java
+ * @run main RecognizedActionTest
+ */
+
+import java.awt.Frame;
+import java.awt.Component;
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.Dimension;
+import java.awt.AWTEvent;
+import java.awt.event.AWTEventListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureEvent;
+
+public class RecognizedActionTest implements AWTEventListener {
+
+ final Frame frame = new Frame();
+ boolean dragGestureRecognized = false;
+ int currentDragAction = DnDConstants.ACTION_NONE;
+
+ final int[] modifiers = {
+ 0,
+ InputEvent.CTRL_DOWN_MASK,
+ InputEvent.SHIFT_DOWN_MASK,
+ InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK
+ };
+
+ final DragSource dragSource = DragSource.getDefaultDragSource();
+ final DragGestureListener dragGestureListener = new DragGestureListener() {
+
+ public void dragGestureRecognized(DragGestureEvent dge) {
+ dragGestureRecognized = true;
+
+ if (dge.getDragAction() != currentDragAction) {
+ throw new RuntimeException("Expected: " +
+ Integer.toHexString(currentDragAction) +
+ " recognized: " +
+ Integer.toHexString(dge.getDragAction()));
+ }
+ }
+ };
+
+ final Object SYNC_LOCK = new Object();
+ final int FRAME_ACTIVATION_TIMEOUT = 2000;
+ final int MOUSE_RELEASE_TIMEOUT = 1000;
+
+ Component clickedComponent = null;
+
+ public void init() {
+ try {
+ frame.setTitle("Test frame");
+ frame.setBounds(100, 100, 200, 200);
+ dragSource.createDefaultDragGestureRecognizer(frame,
+ DnDConstants.ACTION_COPY |
+ DnDConstants.ACTION_MOVE |
+ DnDConstants.ACTION_LINK,
+ dragGestureListener);
+
+ frame.getToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK);
+ frame.setVisible(true);
+ Thread.sleep(100);
+
+ final Robot robot = new Robot();
+ robot.waitForIdle();
+
+ Thread.sleep(FRAME_ACTIVATION_TIMEOUT);
+
+ final Point srcPoint = frame.getLocationOnScreen();
+ Dimension d = frame.getSize();
+ srcPoint.translate(d.width / 2, d.height / 2);
+
+ if (!pointInComponent(robot, srcPoint, frame)) {
+ throw new RuntimeException("WARNING: Couldn't locate source frame.");
+ }
+
+ final Point dstPoint = new Point(srcPoint);
+ dstPoint.translate(d.width / 4, d.height / 4);
+
+ if (!pointInComponent(robot, dstPoint, frame)) {
+ throw new RuntimeException("WARNING: Couldn't locate target frame.");
+ }
+
+ for (int i = 0; i < modifiers.length; i++) {
+ currentDragAction = convertModifiersToDropAction(modifiers[i]);
+ dragGestureRecognized = false;
+ final Point curPoint = new Point(srcPoint);
+ robot.mouseMove(curPoint.x, curPoint.y);
+
+ switch (modifiers[i]) {
+ case InputEvent.SHIFT_DOWN_MASK:
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.waitForIdle();
+ break;
+
+ case InputEvent.CTRL_DOWN_MASK:
+ robot.keyPress(KeyEvent.VK_CONTROL);
+ robot.waitForIdle();
+ break;
+
+ case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
+ robot.keyPress(KeyEvent.VK_CONTROL);
+ robot.waitForIdle();
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.waitForIdle();
+ break;
+
+ default:
+ break;
+ }
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ Thread.sleep(100);
+
+ for (; !curPoint.equals(dstPoint) && !dragGestureRecognized;
+ curPoint.translate(sign(dstPoint.x - curPoint.x),
+ sign(dstPoint.y - curPoint.y))) {
+ robot.mouseMove(curPoint.x, curPoint.y);
+ Thread.sleep(50);
+ }
+ Thread.sleep(100);
+
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+
+ switch (modifiers[i]) {
+ case InputEvent.SHIFT_DOWN_MASK:
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.waitForIdle();
+ break;
+
+ case InputEvent.CTRL_DOWN_MASK:
+ robot.keyRelease(KeyEvent.VK_CONTROL);
+ robot.waitForIdle();
+ break;
+
+ case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
+ robot.keyRelease(KeyEvent.VK_CONTROL);
+ robot.waitForIdle();
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.waitForIdle();
+ break;
+
+ default:
+ break;
+ }
+ Thread.sleep(100);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("The test failed.");
+ }
+ }
+
+ public int sign(int n) {
+ return n < 0 ? -1 : n == 0 ? 0 : 1;
+ }
+
+ public void reset() {
+ clickedComponent = null;
+ }
+
+ public void eventDispatched(AWTEvent e) {
+ if (e.getID() == MouseEvent.MOUSE_RELEASED) {
+ clickedComponent = (Component) e.getSource();
+ synchronized (SYNC_LOCK) {
+ SYNC_LOCK.notifyAll();
+ }
+ }
+ }
+
+ public boolean pointInComponent(Robot robot, Point p, Component comp)
+ throws InterruptedException {
+ reset();
+ robot.mouseMove(p.x, p.y);
+ robot.waitForIdle();
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.waitForIdle();
+ synchronized (SYNC_LOCK) {
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT);
+ }
+
+ Component c = clickedComponent;
+
+ while (c != null && c != comp) {
+ c = c.getParent();
+ }
+
+ return c == comp;
+ }
+
+ public void dispose() {
+ frame.dispose();
+ }
+
+ public int convertModifiersToDropAction(int modifiers) {
+ int dropAction = DnDConstants.ACTION_NONE;
+
+ switch (modifiers & (InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) {
+ case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
+ dropAction = DnDConstants.ACTION_LINK;
+ break;
+
+ case InputEvent.CTRL_DOWN_MASK:
+ dropAction = DnDConstants.ACTION_COPY;
+ break;
+
+ case InputEvent.SHIFT_DOWN_MASK:
+ dropAction = DnDConstants.ACTION_MOVE;
+ break;
+
+ default:
+ dropAction = DnDConstants.ACTION_MOVE;
+ break;
+ }
+
+ return dropAction;
+ }
+
+ public static void main(String args[]) {
+ RecognizedActionTest actionTest = new RecognizedActionTest();
+ actionTest.init();
+ actionTest.dispose();
+ }
+}
--- a/test/jdk/java/lang/String/concat/StringConcatFactoryInvariants.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/java/lang/String/concat/StringConcatFactoryInvariants.java Wed Nov 29 22:40:23 2017 +0100
@@ -282,6 +282,30 @@
// Advanced factory: public Lookup is rejected
fail("Passing public Lookup",
() -> StringConcatFactory.makeConcatWithConstants(MethodHandles.publicLookup(), methodName, mtEmpty, recipeEmpty));
+
+ // Zero inputs
+ {
+ MethodType zero = MethodType.methodType(String.class);
+ CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, zero);
+ test("", (String) cs.getTarget().invokeExact());
+
+ cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "");
+ test("", (String) cs.getTarget().invokeExact());
+ }
+
+ // One input
+ {
+ MethodType zero = MethodType.methodType(String.class);
+ MethodType one = MethodType.methodType(String.class, String.class);
+ CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, one);
+ test("A", (String) cs.getTarget().invokeExact("A"));
+
+ cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, one, "\1");
+ test("A", (String) cs.getTarget().invokeExact("A"));
+
+ cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "\2", "A");
+ test("A", (String) cs.getTarget().invokeExact());
+ }
}
public static void ok(String msg, Callable runnable) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/imageio/plugins/png/PngLargeIHDRDimensionTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8190332
+ * @summary Test verifies whether PNGImageReader throws IIOException
+ * or not when IHDR width value is very high.
+ * @run main PngLargeIHDRDimensionTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Base64;
+import javax.imageio.IIOException;
+import javax.imageio.ImageIO;
+
+public class PngLargeIHDRDimensionTest {
+
+ /*
+ * IHDR width is very large and when we try to create buffer to store
+ * image information of each row it overflows and we get
+ * NegativeArraySizeException without the fix for this bug.
+ */
+ private static String negativeArraySizeExceptionInput = "iVBORw0KGgoAAAANS"
+ + "UhEUg////0AAAABEAIAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAAB"
+ + "JRU5ErkJgggo=";
+
+ /*
+ * IHDR width is ((2 to the power of 31) - 2), which is the maximum VM
+ * limit to create an array we get OutOfMemoryError without the fix
+ * for this bug.
+ */
+ private static String outOfMemoryErrorInput = "iVBORw0KGgoAAAANSUhEUgAAAAF/"
+ + "///+CAAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5"
+ + "ErkJgggo=";
+
+ private static InputStream input;
+ private static Boolean firstTestFailed = true, secondTestFailed = true;
+ public static void main(String[] args) throws java.io.IOException {
+ byte[] inputBytes = Base64.getDecoder().
+ decode(negativeArraySizeExceptionInput);
+ input = new ByteArrayInputStream(inputBytes);
+
+ try {
+ ImageIO.read(input);
+ } catch (IIOException e) {
+ firstTestFailed = false;
+ }
+
+ inputBytes = Base64.getDecoder().decode(outOfMemoryErrorInput);
+ input = new ByteArrayInputStream(inputBytes);
+
+ try {
+ ImageIO.read(input);
+ } catch (IIOException e) {
+ secondTestFailed = false;
+ }
+
+ if (firstTestFailed || secondTestFailed) {
+ throw new RuntimeException("Test doesn't throw required"
+ + " IIOException");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/imageio/plugins/png/PngMultipleImageReadTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8191431
+ * @summary Test verifies that whether we can use same PNGImageReader instance
+ * to read multiple images or not. It also verifies whether
+ * imageStartPosition in PNGImageReader is updated properly when we
+ * use same PNGImageReader instance to read multiple images.
+ * @run main PngMultipleImageReadTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+
+public class PngMultipleImageReadTest {
+
+ private static final ImageReader PNG_READER =
+ ImageIO.getImageReadersByMIMEType("image/png").next();
+
+ public static void main(String[] args) throws IOException {
+
+ /*
+ * First we create a PNG image without palette so that the IDAT
+ * start position in the stream is at some position 'x'.
+ */
+ BufferedImage imageWithoutPalette =
+ new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g1 = imageWithoutPalette.createGraphics();
+ g1.setColor(Color.WHITE);
+ g1.fillRect(0, 0, 20, 20);
+ g1.dispose();
+ // write and read the image without palette
+ writeAndReadImage(imageWithoutPalette);
+
+ /*
+ * We create another PNG image with PLTE(palette) chunk so that
+ * now the IDAT start position is at some 'x + y'.
+ */
+ IndexColorModel cm = new IndexColorModel(
+ 3,
+ 1,
+ new byte[]{10}, // r
+ new byte[]{10}, // g
+ new byte[]{10}); // b
+ BufferedImage imageWithPalette = new BufferedImage(
+ 10, 10,
+ BufferedImage.TYPE_BYTE_INDEXED,
+ cm);
+ Graphics2D g2 = imageWithPalette.createGraphics();
+ g2.setColor(Color.BLACK);
+ g2.fillRect(0, 0, 10, 10);
+ g2.dispose();
+ // write and read the image with palette
+ writeAndReadImage(imageWithPalette);
+ }
+
+ private static void writeAndReadImage(BufferedImage image)
+ throws IOException {
+ File output = File.createTempFile("output", ".png");
+ ImageInputStream stream = null;
+ try {
+ ImageIO.write(image, "png", output);
+
+ stream = ImageIO.createImageInputStream(output);
+ ImageReadParam param = PNG_READER.getDefaultReadParam();
+ PNG_READER.setInput(stream, true, true);
+ PNG_READER.read(0, param);
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ Files.delete(output.toPath());
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Cert.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * The certificates and corresponding private keys used by the test.
+ * All of certificates uses relative weak key size and hash algorithm, then
+ * all JDK releases can load them. Accordingly, a custom java.security file is
+ * provided to make sure such weak key sizes and algorithms are not blocked by
+ * any JDK build.
+ */
+public enum Cert {
+
+ // This certificate is generated by the below command:
+ // openssl req -x509 -newkey rsa:1024 -days 7300 \
+ // -subj "/CN=RSA_SHA1_1024" -sha1 \
+ // -keyout key.pem -out cert.pem
+ RSA_SHA1_1024(
+ SignatureAlgorithm.RSA,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIB/jCCAWegAwIBAgIJANPuKkD7/jxkMA0GCSqGSIb3DQEBBQUAMBgxFjAUBgNV\n" +
+ "BAMMDVJTQV9TSEExXzEwMjQwHhcNMTcwOTA3MDIwNTM0WhcNMzcwOTAyMDIwNTM0\n" +
+ "WjAYMRYwFAYDVQQDDA1SU0FfU0hBMV8xMDI0MIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" +
+ "ADCBiQKBgQC3v7UeIxD5bdv4mqwcpah7sNxpI3IxUFzI2ao1g1jVzDPZt9Zawa3K\n" +
+ "H+m9al1Fg2X1dyNeRlbiXavcIZOQwZqNj08zJEwAdICP8iOnXQ2HUv5cpzArOPTu\n" +
+ "GY3flhf39xgiWsSdfb+cP0QsWNagNU8EtebbHndv8W+2K5JEdlpwQQIDAQABo1Aw\n" +
+ "TjAdBgNVHQ4EFgQU32KqdiGyzg39chNt/OwQzGOlUyAwHwYDVR0jBBgwFoAU32Kq\n" +
+ "diGyzg39chNt/OwQzGOlUyAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOB\n" +
+ "gQAWx8y45IIWWhy44cuQs0qcSDQihIvhXB3pvlpCNdfsSrVoaaH8lrOVjTC718ip\n" +
+ "fE1sF8I9niLHUg8WrAzdQRDsKyUhDUhEEJ7w1ffxwf8bcI9+NgWwEix0Dazzkub8\n" +
+ "2IRXuZ3dGwzoI54XtxvKMFH86nJEj4M/XQGrc9bnlhcn4g==\n" +
+ "-----END CERTIFICATE-----",
+ "30820278020100300d06092a864886f70d0101010500048202623082025e0201" +
+ "0002818100b7bfb51e2310f96ddbf89aac1ca5a87bb0dc69237231505cc8d9aa" +
+ "358358d5cc33d9b7d65ac1adca1fe9bd6a5d458365f577235e4656e25dabdc21" +
+ "9390c19a8d8f4f33244c0074808ff223a75d0d8752fe5ca7302b38f4ee198ddf" +
+ "9617f7f718225ac49d7dbf9c3f442c58d6a0354f04b5e6db1e776ff16fb62b92" +
+ "44765a7041020301000102818100b2c5afdf5c5a9d72c73b7eb0c9465b3fcc79" +
+ "0549d946255bc0861555ef2eb503f1c67757f400cfa7019996123020fb906d5b" +
+ "b66b789ffba90b16270cbd1fbfcf285a821dcdc78fd8f17f399eb231ce9724db" +
+ "af60f9dd20f3e57bb4c0f9fdc9069589b82d442dd868d48c031eb782e27f9e70" +
+ "8469f9b3d5b1b23cee5bf1b41781024100dec184ea77c2126c6bc0c01ba727b4" +
+ "642587d63811240932334dc80c7976e0f715f156e52b352a25e5c52542af2b5f" +
+ "68a29a9b68858f313c4375cc78ec03d859024100d32be8375f52cbe904002321" +
+ "6977aee83fa88bf536d4052d2ed578727d7b7e5aeef91fc52b34c1b6638c00f0" +
+ "4c6985fdaaa2d6e72adbcc7d10ed8bafff69da29024100ae8210acd6f13519b7" +
+ "38a3c7862636ce1610daa3c5d9e3526e9acad3eafc54b57d7d3a44029b7dcf7e" +
+ "b7f9beca1842806892929949b8aa2bb9f5b9202a55c0d1024100887dc0c2c9a2" +
+ "429a823374818c2207b3a631d304d443867505e884c9bbc1ae9228146e2c8b18" +
+ "b67ca52b411010d3c3ff89e366f454076dcd08bc01a5e8790ac102402321988a" +
+ "2003e19c878791d402a7c0acdd1b6dd27203ed88f86a0e3a390ee57c0cd277f3" +
+ "ea5df6440dbc8bdb4c8b3c28fc77e6991bc4ed3f4dc0619a5b953e8e"),
+
+ // This certificate is generated by the below command:
+ // openssl req -x509 -newkey rsa:1024 -days 7300 \
+ // -subj "/CN=www.example.com" -sha1 \
+ // -keyout key.pem -out cert.pem
+ RSA_EXAMPLE_SHA1_1024(
+ SignatureAlgorithm.RSA,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICAjCCAWugAwIBAgIJAK6TC9eDtZg4MA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV\n" +
+ "BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNzExMDIwNTA5NDRaFw0zNzEwMjgwNTA5\n" +
+ "NDRaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEF\n" +
+ "AAOBjQAwgYkCgYEAtt5kxFTzJuoxJR2UgeXUxCw7TfL3FeK3lCrU3vruBe3XKKvF\n" +
+ "oyCxf/B5ucm22gzMfOvJBWRg6KrNTrXGI1LtlmAYNDM5J0lK2N/neKOm3Qxe0d1W\n" +
+ "AZ1lwgrMNirsWu+r4UPNMq5UohL5nqVU9WwVa12t0GF3er3k32tMTBqSclcCAwEA\n" +
+ "AaNQME4wHQYDVR0OBBYEFNc8tKGfZdFyaY0ZslwGLt1kpRYAMB8GA1UdIwQYMBaA\n" +
+ "FNc8tKGfZdFyaY0ZslwGLt1kpRYAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF\n" +
+ "BQADgYEAc71ZO83YEw9WvhxDEng9tMYUhJnNZJss6+gfWjZ487aiEGnS+VgKsHWz\n" +
+ "DBLBrYe9Ag5L9f1HtPNheUbnhhBbQ607jOG/wfmpi4VoU3myB5uxOfeAZdXDOB5x\n" +
+ "bv3t7KcEhgmPjB/e123jrBK8qnAYmDlQVlkZScctB3I1OuA2Po4=\n" +
+ "-----END CERTIFICATE-----",
+ "30820277020100300d06092a864886f70d0101010500048202613082025d0201" +
+ "0002818100b6de64c454f326ea31251d9481e5d4c42c3b4df2f715e2b7942ad4" +
+ "defaee05edd728abc5a320b17ff079b9c9b6da0ccc7cebc9056460e8aacd4eb5" +
+ "c62352ed96601834333927494ad8dfe778a3a6dd0c5ed1dd56019d65c20acc36" +
+ "2aec5aefabe143cd32ae54a212f99ea554f56c156b5dadd061777abde4df6b4c" +
+ "4c1a927257020301000102818048af52bc1acbdededd13d4930fa28b9441c47c" +
+ "b222f5c6fc92df07676db3a815a61c9b51de0a03a347b10a609bd6459a0dd926" +
+ "38877261686a5c6bb1ca9e8ea2373870af7685e7d6cebd66faba65af2ef04bd9" +
+ "1244ae56900fcd6ce11207d8c4040176e4ba9fef3d563741a1027b229134cfe1" +
+ "c0a90d9c8eba9ce6349835e769024100e82494b6f777c784ffc29298d033e11d" +
+ "af46f0d464c4dbd950d46bcd697d0f0b49a77699f0111d408e8748f2b461ab8f" +
+ "210071c9c20d8ecee3ae229cb9c3954b024100c9a976f0011fcdc0ca7fb2f679" +
+ "974fa85d420c604ca7ff64fe4667a44f73088eef290d22195474039760e99325" +
+ "3ca45ee444588b150467d14451d3c45dab0ba5024019df39d3ca70c703c39d63" +
+ "c9342b1403c2ed1d1a0ec101df8e6a9e391e7099a4a068d187068261c8381a4b" +
+ "bf00eb81bb49ea4ac439a4592e25a1daa9acea67510241008c4640007497bdd4" +
+ "94473da26b33d06a29ecae9531dd4e2edf1cf42cfc42e53a1fac2b8183a3164c" +
+ "053999600c6fe15a4c682a3b1cb482ceb33a4416fc9ce52d024100e4f08cd10a" +
+ "5c8face0b20db86443d0a42e34dfdde236dae4f042a06dd3aff7ca159f8aa3b7" +
+ "854df41d510148096155204f2bf46c4a96e271747a4126a66ade6c"),
+
+ // This certificate is generated by the below commands:
+ // openssl dsaparam -genkey 1024 -out key.pem
+ // openssl req -x509 -new -key key.pem -days 7300 \
+ // -subj "/CN=DSA_SHA1_1024" -sha1 -out cert.pem
+ DSA_SHA1_1024(
+ SignatureAlgorithm.DSA,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICuzCCAnugAwIBAgIJAMAMLRrhQWQFMAkGByqGSM44BAMwGDEWMBQGA1UEAwwN\n" +
+ "RFNBX1NIQTFfMTAyNDAeFw0xNzExMDIwNjA4MDRaFw0zNzEwMjgwNjA4MDRaMBgx\n" +
+ "FjAUBgNVBAMMDURTQV9TSEExXzEwMjQwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEA\n" +
+ "8CspE1sE84pJ4YxzVHFEDNJvBaIxsbax03pDwNHr/ogP9PVwF9z1jT6hpC5WluHG\n" +
+ "g5n5gqpF2XpBhX2fKm1qqZWRxNvHKo0+zzAhUqMrvRJqcjlL4ijXndHldt67/VKS\n" +
+ "0eTKi9m64c+yJx80YYphCO5b93d2sTM29z8QZOlrbD8CFQCmttKnPAOk4uz8Z8cV\n" +
+ "uPGeGOMB9wKBgCItgPpAjW0srIwCaDysDNpydX6hB+1NTy1gFYl24n8edLGbR0mZ\n" +
+ "isteBd6LjMtgicRmtKZzKxW7igxoVvR3WHpTucFjms5NRNjPaj5wt3DxoXn4hyWk\n" +
+ "LzMvDeBvi+jKJiO0jnQ3+1NDOlAQy6ukeH59/gxZ3UmcNxDlAQ/IYHcpA4GEAAKB\n" +
+ "gEgvi72gL+zax7Y2hg4PL1PqZx2jFp0XlTIugiTrcsGytrAnn+/s2+3xVyVyvVMn\n" +
+ "0z5yL5eP9cdGA7qV1+7n6KJ8jNAhLCBSiC6x5ekd88aTlqnmt5lstk4w0Q0zSa58\n" +
+ "Hp6dCFg2Irk6Z9ERKaXJJBBS6reaFeATVROhN/LEEzzvo1AwTjAdBgNVHQ4EFgQU\n" +
+ "jb+HHABclGNR4lpf19nHFZpfwPQwHwYDVR0jBBgwFoAUjb+HHABclGNR4lpf19nH\n" +
+ "FZpfwPQwDAYDVR0TBAUwAwEB/zAJBgcqhkjOOAQDAy8AMCwCFDB3F/m6jsZdHaoy\n" +
+ "1xTp2U8uHBO+AhQYzeJuJd8/qRSDVLs8mesE8TQg2g==\n" +
+ "-----END CERTIFICATE-----",
+ "3082014a0201003082012b06072a8648ce3804013082011e02818100f02b2913" +
+ "5b04f38a49e18c735471440cd26f05a231b1b6b1d37a43c0d1ebfe880ff4f570" +
+ "17dcf58d3ea1a42e5696e1c68399f982aa45d97a41857d9f2a6d6aa99591c4db" +
+ "c72a8d3ecf302152a32bbd126a72394be228d79dd1e576debbfd5292d1e4ca8b" +
+ "d9bae1cfb2271f34618a6108ee5bf77776b13336f73f1064e96b6c3f021500a6" +
+ "b6d2a73c03a4e2ecfc67c715b8f19e18e301f7028180222d80fa408d6d2cac8c" +
+ "02683cac0cda72757ea107ed4d4f2d60158976e27f1e74b19b4749998acb5e05" +
+ "de8b8ccb6089c466b4a6732b15bb8a0c6856f477587a53b9c1639ace4d44d8cf" +
+ "6a3e70b770f1a179f88725a42f332f0de06f8be8ca2623b48e7437fb53433a50" +
+ "10cbaba4787e7dfe0c59dd499c3710e5010fc8607729041602146ef9db36045f" +
+ "bcd8c7fd82ba29c5c5057ed11c7f"),
+
+ // This certificate is generated by the below commands:
+ // openssl dsaparam -genkey 1024 -out key.pem
+ // openssl req -x509 -new -key key.pem -days 7300 \
+ // -subj "/CN=www.example.com" -sha1 -out cert.pem
+ DSA_EXAMPLE_SHA1_1024(
+ SignatureAlgorithm.DSA,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICwDCCAoCgAwIBAgIJAI5mKbdK5ZqyMAkGByqGSM44BAMwGjEYMBYGA1UEAwwP\n" +
+ "d3d3LmV4YW1wbGUuY29tMB4XDTE3MTEwMjA1NDczOVoXDTM3MTAyODA1NDczOVow\n" +
+ "GjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBtzCCASwGByqGSM44BAEwggEf\n" +
+ "AoGBANVGWRSlxVZQKlVrTDcU/6Mr8QFlR3kGKmkvdbTHH1EhcP7YlZ7CJ30VBDbN\n" +
+ "LS2HvN3HHNooJ7hHBheL5Yz8EZIUa95TzPukZ1TmCo9fufR5i9HWj9Z8jLhyqx3l\n" +
+ "iUZOYN9H0MSn4ftK6dr5oTz2ZGYDblXDCq6R8qZfuw1URFqrAhUArx0nmGEI/1S/\n" +
+ "qyxnV4I6ItOntxMCgYEAxZKIZ/7aOGfzaQG2wRFdD/viHBZkkcxCsgmPUroQVUIw\n" +
+ "dqmUnfYk8cb02LCevhhSwcjfocQsA3y1jufIUdWaHuIB9W3EsFJQNd/Byh9j/pRD\n" +
+ "7zH/8lnBzJh2S7y10Vg840STVo5+ekZb4E+W7KK5gUaEQ6kAtUIIB0xjNz7RWs4D\n" +
+ "gYQAAoGAPVQKWqJSlMrbU4XEsx50Ur8P84CwMnS7WcQNLnih1ScaK2BijgVj5Fny\n" +
+ "9JZxITwj7XD7FWriq3kTjbydi3iAvrgVWij79x5Z7fTRCuoBVmtnAFkVGalwbGr2\n" +
+ "ghz70y6hep2Evb1pRCrHjRkMaJFE5Y2CA7VbpKoat+j47/LkXJ2jUDBOMB0GA1Ud\n" +
+ "DgQWBBSVjWy3SpaDfnFo+37mZJqX2aybzTAfBgNVHSMEGDAWgBSVjWy3SpaDfnFo\n" +
+ "+37mZJqX2aybzTAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUd5NOlcfX\n" +
+ "5rakT9H8UzlFcFQLr0MCFGrEYvlFUf/HJOH4FwXS2jEholBB\n" +
+ "-----END CERTIFICATE-----",
+ "3082014c0201003082012c06072a8648ce3804013082011f02818100d5465914" +
+ "a5c556502a556b4c3714ffa32bf101654779062a692f75b4c71f512170fed895" +
+ "9ec2277d150436cd2d2d87bcddc71cda2827b84706178be58cfc1192146bde53" +
+ "ccfba46754e60a8f5fb9f4798bd1d68fd67c8cb872ab1de589464e60df47d0c4" +
+ "a7e1fb4ae9daf9a13cf66466036e55c30aae91f2a65fbb0d54445aab021500af" +
+ "1d27986108ff54bfab2c6757823a22d3a7b71302818100c5928867feda3867f3" +
+ "6901b6c1115d0ffbe21c166491cc42b2098f52ba1055423076a9949df624f1c6" +
+ "f4d8b09ebe1852c1c8dfa1c42c037cb58ee7c851d59a1ee201f56dc4b0525035" +
+ "dfc1ca1f63fe9443ef31fff259c1cc98764bbcb5d1583ce34493568e7e7a465b" +
+ "e04f96eca2b981468443a900b54208074c63373ed15ace0417021500abf47692" +
+ "88c6ac41e2802e7eb7addba367339318"),
+
+ // This certificate is generated by the below commands:
+ // openssl ecparam -name prime256v1 -genkey -out key.pem
+ // openssl req -new -key key.pem -x509 -nodes -days 7300 \
+ // -subj "/CN=ECDSA_SHA1_prime256v1" -sha1 -out cert.pem
+ ECDSA_SHA1_PRIME256V1(
+ SignatureAlgorithm.ECDSA,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBhDCCASygAwIBAgIJAKW4wuujp9JbMAkGByqGSM49BAEwIDEeMBwGA1UEAwwV\n" +
+ "RUNEU0FfU0hBMV9wcmltZTI1NnYxMB4XDTE3MDkwNzAyMTA0MVoXDTM3MDkwMjAy\n" +
+ "MTA0MVowIDEeMBwGA1UEAwwVRUNEU0FfU0hBMV9wcmltZTI1NnYxMFkwEwYHKoZI\n" +
+ "zj0CAQYIKoZIzj0DAQcDQgAEdbE+AMwsFBf73YXRVwsvsx2dMt1xgDxj/4pN+BfY\n" +
+ "LWnO94beeZcrCJ1/N8CHmDOce7KRDR6/9kpi20wFAVXZ3KNQME4wHQYDVR0OBBYE\n" +
+ "FA/hB2ODDNdz1JF08u2uhknhlsVoMB8GA1UdIwQYMBaAFA/hB2ODDNdz1JF08u2u\n" +
+ "hknhlsVoMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNHADBEAiBNxv2L2FW+6+w/\n" +
+ "QtDe+YSUNRj3F8QrpLkfGk7rVaOiHQIgVF2pWJ5ytg0pbCuO8Bh+UZ7zfZUD03s8\n" +
+ "ZuIYW7RtMe0=\n" +
+ "-----END CERTIFICATE-----",
+ "308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02" +
+ "010104204d901d5efd0e3def78d5307788a4c760115effce4b9e2c31ae5860b6" +
+ "c11915aca1440342000475b13e00cc2c1417fbdd85d1570b2fb31d9d32dd7180" +
+ "3c63ff8a4df817d82d69cef786de79972b089d7f37c08798339c7bb2910d1ebf" +
+ "f64a62db4c050155d9dc"),
+
+ // This certificate is generated by the below commands:
+ // openssl ecparam -name prime256v1 -genkey -out key.pem
+ // openssl req -new -key key.pem -x509 -nodes -days 7300 \
+ // -subj "/CN=www.example.com" -sha1 -out cert.pem
+ ECDSA_EXAMPLE_SHA1_PRIME256V1(
+ SignatureAlgorithm.ECDSA,
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBeDCCASCgAwIBAgIJAMxOXBpiJ5mDMAkGByqGSM49BAEwGjEYMBYGA1UEAwwP\n" +
+ "d3d3LmV4YW1wbGUuY29tMB4XDTE3MTEwMjA1MTg0MVoXDTM3MTAyODA1MTg0MVow\n" +
+ "GjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
+ "AQcDQgAER9IyuwyrJ7X9DmIqGC3YNTlWBt4Fo/Y3RnlcxhTVxb/ZAYVNhqe4MbSM\n" +
+ "2nsVnYMjjXXDav1plNKvmgGDf9s/saNQME4wHQYDVR0OBBYEFHNUTaIIEA89uNKH\n" +
+ "OOUgJ981Qj5HMB8GA1UdIwQYMBaAFHNUTaIIEA89uNKHOOUgJ981Qj5HMAwGA1Ud\n" +
+ "EwQFMAMBAf8wCQYHKoZIzj0EAQNHADBEAiBCW59S1nE15j8euO6/q9bM6J9Ci5xJ\n" +
+ "WWAVznGGxnS/HgIgFaFKC31uxTXoBN7QN0yW/umQgJ0nsjwj7Pnxc0wNyw8=\n" +
+ "-----END CERTIFICATE-----",
+ "308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02" +
+ "010104209aa3784cd0c1fe0553e59b3c7b8f08c8fdaffd94f34e2c1683243a79" +
+ "7b64b673a1440342000447d232bb0cab27b5fd0e622a182dd835395606de05a3" +
+ "f63746795cc614d5c5bfd901854d86a7b831b48cda7b159d83238d75c36afd69" +
+ "94d2af9a01837fdb3fb1");
+
+ public final SignatureAlgorithm signatureAlgorithm;
+ public final String certMaterials;
+ public final String privKeyMaterials;
+
+ private Cert(
+ SignatureAlgorithm signatureAlgorithm,
+ String certMaterials,
+ String privKeyMaterials) {
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.certMaterials = certMaterials;
+ this.privKeyMaterials = privKeyMaterials;
+ }
+
+ // Two certificates (mainCert and exampleCert) are selected to respect the
+ // specified cipher suite. SNI-associated cases specify exampleCert as desired.
+ public static Cert[] getCerts(String cipherSuite) {
+ Cert mainCert = Cert.DSA_SHA1_1024;
+ Cert exampleCert = Cert.DSA_EXAMPLE_SHA1_1024;
+ if (cipherSuite.contains("_ECDHE_RSA_")) {
+ mainCert = Cert.RSA_SHA1_1024;
+ exampleCert = Cert.RSA_EXAMPLE_SHA1_1024;
+ } else if (cipherSuite.contains("_EC")) {
+ mainCert = Cert.ECDSA_SHA1_PRIME256V1;
+ exampleCert = Cert.ECDSA_EXAMPLE_SHA1_PRIME256V1;
+ } else if (cipherSuite.contains("_RSA")) {
+ mainCert = Cert.RSA_SHA1_1024;
+ exampleCert = Cert.RSA_EXAMPLE_SHA1_1024;
+ }
+ System.out.printf("mainCert=%s, exampleCert=%s%n",
+ mainCert, exampleCert);
+ return new Cert[] { mainCert, exampleCert };
+ }
+}
+
+enum SignatureAlgorithm {
+
+ RSA, DSA, ECDSA;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Client.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/*
+ * A simple SSL socket client.
+ */
+public class Client {
+
+ private final SSLSocket socket;
+
+ public Client(SSLContext context) throws Exception {
+ SSLSocketFactory socketFactory = context.getSocketFactory();
+ socket = (SSLSocket) socketFactory.createSocket();
+ socket.setSoTimeout(Utils.TIMEOUT);
+ }
+
+ public Client(Cert... certs) throws Exception {
+ this(Utils.createSSLContext(certs));
+ }
+
+ private SSLSession getSession() {
+ return socket.getSession();
+ }
+
+ private void setEnabledCipherSuites(String... cipherSuites) {
+ socket.setEnabledCipherSuites(cipherSuites);
+ }
+
+ private void setEnabledProtocols(String... protocols) {
+ socket.setEnabledProtocols(protocols);
+ }
+
+ @SuppressWarnings(value = { "unchecked", "rawtypes" })
+ private void setServerName(String hostname) {
+ List serverNames = new ArrayList();
+ serverNames.add(createSNIHostName(hostname));
+ SSLParameters params = socket.getSSLParameters();
+ params.setServerNames(serverNames);
+ socket.setSSLParameters(params);
+ }
+
+ // Create SNIHostName via reflection due to pre-8 JDK builds don't support
+ // SNI. Those JDK builds cannot find classes SNIServerName and SNIHostName.
+ private Object createSNIHostName(String hostname) {
+ try {
+ Class<?> clazz = Class.forName("javax.net.ssl.SNIHostName");
+ return clazz.getConstructor(String.class).newInstance(hostname);
+ } catch (Exception e) {
+ throw new RuntimeException("Creates SNIHostName failed!", e);
+ }
+ }
+
+ private void setApplicationProtocols(String... protocols) {
+ SSLParameters params = socket.getSSLParameters();
+ params.setApplicationProtocols(protocols);
+ socket.setSSLParameters(params);
+ }
+
+ private String getNegotiatedApplicationProtocol() {
+ return socket.getApplicationProtocol();
+ }
+
+ private void oneTimeConnect(String host, int port) throws IOException {
+ socket.connect(new InetSocketAddress(host, port));
+
+ OutputStream out = socket.getOutputStream();
+ out.write('C');
+ out.flush();
+
+ InputStream in = socket.getInputStream();
+ in.read();
+ }
+
+ public void close() throws IOException {
+ socket.close();
+ }
+
+ public static void main(String[] args) throws IOException {
+ System.out.println("----- Client start -----");
+ int port = Integer.valueOf(System.getProperty(Utils.PROP_PORT));
+
+ String protocol = System.getProperty(Utils.PROP_PROTOCOL);
+ String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
+ String serverName = System.getProperty(Utils.PROP_SERVER_NAME);
+ String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
+ boolean supportsSNIOnServer
+ = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_SERVER);
+ boolean supportsSNIOnClient
+ = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_CLIENT);
+ boolean supportsALPNOnServer
+ = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
+ boolean supportsALPNOnClient
+ = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT);
+ boolean negativeCase
+ = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_CLIENT);
+ System.out.println(Utils.join(Utils.PARAM_DELIMITER,
+ "ClientJDK=" + System.getProperty(Utils.PROP_CLIENT_JDK),
+ "Protocol=" + protocol,
+ "CipherSuite=" + cipherSuite,
+ "ServerName=" + serverName,
+ "AppProtocols=" + appProtocols));
+
+ Status status = Status.SUCCESS;
+ Client client = null;
+ try {
+ client = new Client(Cert.getCerts(cipherSuite));
+ client.setEnabledProtocols(protocol);
+ client.setEnabledCipherSuites(cipherSuite);
+
+ if (serverName != null) {
+ if (supportsSNIOnClient) {
+ client.setServerName(serverName);
+ } else {
+ System.out.println(
+ "Ignored due to client doesn't support SNI.");
+ }
+ }
+
+ if (appProtocols != null) {
+ if (supportsALPNOnClient) {
+ client.setApplicationProtocols(
+ Utils.split(appProtocols, Utils.VALUE_DELIMITER));
+ } else {
+ System.out.println(
+ "Ignored due to client doesn't support ALPN.");
+ }
+ }
+
+ client.oneTimeConnect("localhost", port);
+
+ if (serverName != null && supportsSNIOnServer
+ && supportsSNIOnClient) {
+ X509Certificate cert
+ = (X509Certificate) client.getSession().getPeerCertificates()[0];
+ String subject
+ = cert.getSubjectX500Principal().getName();
+ if (!subject.contains(serverName)) {
+ System.out.println("Unexpected server: " + subject);
+ status = Status.FAIL;
+ }
+ }
+
+ if (appProtocols != null && supportsALPNOnServer
+ && supportsALPNOnClient) {
+ String negoAppProtocol
+ = client.getNegotiatedApplicationProtocol();
+ String expectedNegoAppProtocol
+ = System.getProperty(Utils.PROP_NEGO_APP_PROTOCOL);
+ if (!expectedNegoAppProtocol.equals(negoAppProtocol)) {
+ System.out.println("Unexpected negotiated app protocol: "
+ + negoAppProtocol);
+ status = Status.FAIL;
+ }
+ }
+
+ if (status != Status.FAIL) {
+ status = negativeCase
+ ? Status.UNEXPECTED_SUCCESS
+ : Status.SUCCESS;
+ }
+ } catch (Exception exception) {
+ status = Utils.handleException(exception, negativeCase);
+ } finally {
+ if (client != null) {
+ client.close();
+ }
+ }
+
+ System.out.println("STATUS: " + status);
+ System.out.println("----- Client end -----");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Compatibility.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 This test is used to check the interop compatibility on JSSE among
+ * different JDK releases.
+ * Note that, this is a manual test. For more details about the test and
+ * its usages, please look through README.
+ *
+ * @library /test/lib
+ * @compile -source 1.6 -target 1.6 JdkUtils.java Parameter.java Server.java Client.java
+ * @run main/manual Compatibility
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class Compatibility {
+
+ public static void main(String[] args) throws Throwable {
+ String javaSecurityFile
+ = System.getProperty("test.src") + "/java.security";
+ boolean debug = Utils.getBoolProperty("debug");
+
+ Set<JdkInfo> jdkInfos = jdkInfoList();
+
+ System.out.println("Test start");
+
+ List<TestCase> testCases = new ArrayList<>();
+ ExecutorService executor = Executors.newCachedThreadPool();
+ PrintStream origStdOut = System.out;
+ PrintStream origStdErr = System.err;
+
+ try (PrintStream printStream = new PrintStream(
+ new FileOutputStream(Utils.TEST_LOG, true))) {
+ System.setOut(printStream);
+ System.setErr(printStream);
+
+ System.out.println(Utils.startHtml());
+ System.out.println(Utils.startPre());
+
+ for (UseCase useCase : UseCase.getAllUseCases()) {
+ for (JdkInfo serverJdk : jdkInfos) {
+ if (useCase.ignoredByJdk(serverJdk)) {
+ continue;
+ }
+
+ Map<String, String> props = new LinkedHashMap<>();
+ if (debug) {
+ props.put("javax.net.debug", "ssl");
+ }
+ props.put("java.security.properties", javaSecurityFile);
+
+ props.put(Utils.PROP_PROTOCOL, useCase.protocol.version);
+ props.put(Utils.PROP_CIPHER_SUITE, useCase.cipherSuite.name());
+ props.put(Utils.PROP_CLIENT_AUTH, useCase.clientAuth.name());
+ if (useCase.appProtocol != AppProtocol.NONE) {
+ props.put(Utils.PROP_APP_PROTOCOLS,
+ Utils.join(Utils.VALUE_DELIMITER,
+ useCase.appProtocol.appProtocols));
+ props.put(Utils.PROP_NEGO_APP_PROTOCOL,
+ useCase.appProtocol.negoAppProtocol);
+ }
+ props.put(Utils.PROP_SERVER_JDK, serverJdk.version);
+
+ props.put(Utils.PROP_SUPPORTS_SNI_ON_SERVER,
+ serverJdk.supportsSNI + "");
+ props.put(Utils.PROP_SUPPORTS_ALPN_ON_SERVER,
+ serverJdk.supportsALPN + "");
+
+ for (JdkInfo clientJdk : jdkInfos) {
+ if (useCase.ignoredByJdk(clientJdk)) {
+ continue;
+ }
+
+ TestCase testCase = new TestCase(serverJdk, clientJdk,
+ useCase);
+ System.out.println(Utils.anchorName(testCase.toString(),
+ "----- Case start -----"));
+ System.out.println(testCase.toString());
+
+ props.put(Utils.PROP_NEGATIVE_CASE_ON_SERVER,
+ testCase.negativeCaseOnServer + "");
+ props.put(Utils.PROP_NEGATIVE_CASE_ON_CLIENT,
+ testCase.negativeCaseOnClient + "");
+
+ Future<OutputAnalyzer> serverFuture = executor.submit(() -> {
+ return runServer(serverJdk.jdkPath, props);
+ });
+ int port = waitForServerStarted();
+ System.out.println("port=" + port);
+
+ props.put(Utils.PROP_PORT, port + "");
+
+ props.put(Utils.PROP_CLIENT_JDK, clientJdk.version);
+
+ props.put(Utils.PROP_SUPPORTS_SNI_ON_CLIENT,
+ clientJdk.supportsSNI + "");
+ props.put(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT,
+ clientJdk.supportsALPN + "");
+ if (useCase.serverName != ServerName.NONE) {
+ props.put(Utils.PROP_SERVER_NAME,
+ useCase.serverName.name);
+ }
+
+ Status clientStatus = null;
+ if (port != -1) {
+ String clientOutput = runClient(clientJdk.jdkPath,
+ props).getOutput();
+ clientStatus = getStatus(clientOutput);
+ }
+
+ String serverOutput = serverFuture.get().getOutput();
+ Status serverStatus = getStatus(serverOutput);
+ testCase.setStatus(caseStatus(serverStatus, clientStatus));
+ testCases.add(testCase);
+ System.out.printf(
+ "ServerStatus=%s, ClientStatus=%s, CaseStatus=%s%n",
+ serverStatus, clientStatus, testCase.getStatus());
+
+ // Confirm the server has stopped.
+ if(new File(Utils.PORT_LOG).exists()) {
+ throw new RuntimeException("Server doesn't stop.");
+ }
+ System.out.println("----- Case end -----");
+ }
+ }
+ }
+
+ System.out.println(Utils.endPre());
+ System.out.println(Utils.endHtml());
+ }
+ System.setOut(origStdOut);
+ System.setErr(origStdErr);
+ executor.shutdown();
+
+ System.out.println("Test end");
+ System.out.println("Report is being generated...");
+ boolean failed = generateReport(testCases);
+ System.out.println("Report is generated.");
+ if (failed) {
+ throw new RuntimeException("At least one case failed. "
+ + "Please check logs for more details.");
+ }
+ }
+
+ private static Status getStatus(String log) {
+ if (log.contains(Status.UNEXPECTED_SUCCESS.name())) {
+ return Status.UNEXPECTED_SUCCESS;
+ } else if (log.contains(Status.SUCCESS.name())) {
+ return Status.SUCCESS;
+ } else if (log.contains(Status.EXPECTED_FAIL.name())) {
+ return Status.EXPECTED_FAIL;
+ } else if (log.contains(Status.TIMEOUT.name())) {
+ return Status.TIMEOUT;
+ } else {
+ return Status.FAIL;
+ }
+ }
+
+ private static Status caseStatus(Status serverStatus, Status clientStatus) {
+ if (clientStatus == null || clientStatus == Status.TIMEOUT) {
+ return serverStatus == Status.EXPECTED_FAIL
+ ? Status.EXPECTED_FAIL
+ : Status.FAIL;
+ } else if (serverStatus == Status.TIMEOUT) {
+ return clientStatus == Status.EXPECTED_FAIL
+ ? Status.EXPECTED_FAIL
+ : Status.FAIL;
+ } else {
+ return serverStatus == clientStatus
+ ? serverStatus
+ : Status.FAIL;
+ }
+ }
+
+ // Retrieves JDK info from the file which is specified by jdkListFile.
+ // If no such file or no JDK is specified by the file, the current testing
+ // JDK will be used.
+ private static Set<JdkInfo> jdkInfoList() throws Throwable {
+ List<String> jdkList = jdkList("jdkListFile");
+ if (jdkList.size() == 0) {
+ jdkList.add(System.getProperty("test.jdk"));
+ }
+
+ Set<JdkInfo> jdkInfoList = new LinkedHashSet<>();
+ for (String jdkPath : jdkList) {
+ JdkInfo jdkInfo = new JdkInfo(jdkPath);
+ // JDK version must be unique.
+ if (!jdkInfoList.add(jdkInfo)) {
+ System.out.println("The JDK version is duplicate: " + jdkPath);
+ }
+ }
+ return jdkInfoList;
+ }
+
+ private static List<String> jdkList(String listFileProp) throws IOException {
+ String listFile = System.getProperty(listFileProp);
+ System.out.println(listFileProp + "=" + listFile);
+ if (listFile != null && new File(listFile).exists()) {
+ return Files.lines(Paths.get(listFile))
+ .filter(line -> { return !line.trim().isEmpty(); })
+ .collect(Collectors.toList());
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ // Checks if server is already launched, and returns server port.
+ private static int waitForServerStarted()
+ throws IOException, InterruptedException {
+ System.out.print("Waiting for server");
+ long deadline = System.currentTimeMillis() + Utils.TIMEOUT;
+ int port;
+ while ((port = getServerPort()) == -1
+ && System.currentTimeMillis() < deadline) {
+ System.out.print(".");
+ TimeUnit.SECONDS.sleep(1);
+ }
+ System.out.println();
+
+ return port;
+ }
+
+ // Retrieves the latest server port from port.log.
+ private static int getServerPort() throws IOException {
+ if (!new File(Utils.PORT_LOG).exists()) {
+ return -1;
+ }
+
+ return Integer.valueOf(
+ Files.lines(Paths.get(Utils.PORT_LOG)).findFirst().get());
+ }
+
+ private static OutputAnalyzer runServer(String jdkPath,
+ Map<String, String> props) {
+ return ProcessUtils.java(jdkPath, props, Server.class);
+ }
+
+ private static OutputAnalyzer runClient(String jdkPath,
+ Map<String, String> props) {
+ return ProcessUtils.java(jdkPath, props, Client.class);
+ }
+
+ // Generates the test result report.
+ private static boolean generateReport(List<TestCase> testCases)
+ throws IOException {
+ boolean failed = false;
+ StringBuilder report = new StringBuilder();
+ report.append(Utils.startHtml());
+ report.append(Utils.tableStyle());
+ report.append(Utils.startTable());
+ report.append(Utils.row(
+ "No.",
+ "ServerJDK",
+ "ClientJDK",
+ "Protocol",
+ "CipherSuite",
+ "ClientAuth",
+ "SNI",
+ "ALPN",
+ "Status"));
+ for (int i = 0, size = testCases.size(); i < size; i++) {
+ TestCase testCase = testCases.get(i);
+
+ report.append(Utils.row(
+ Utils.anchorLink(
+ Utils.TEST_LOG,
+ testCase.toString(),
+ i + ""),
+ testCase.serverJdk.version,
+ testCase.clientJdk.version,
+ testCase.useCase.protocol.version,
+ testCase.useCase.cipherSuite,
+ Utils.boolToStr(
+ testCase.useCase.clientAuth == ClientAuth.TRUE),
+ Utils.boolToStr(
+ testCase.useCase.serverName == ServerName.EXAMPLE),
+ Utils.boolToStr(
+ testCase.useCase.appProtocol == AppProtocol.EXAMPLE),
+ testCase.getStatus()));
+ failed = failed
+ || testCase.getStatus() == Status.FAIL
+ || testCase.getStatus() == Status.UNEXPECTED_SUCCESS;
+ }
+ report.append(Utils.endTable());
+ report.append(Utils.endHtml());
+
+ generateFile("report.html", report.toString());
+ return failed;
+ }
+
+ private static void generateFile(String path, String content)
+ throws IOException {
+ try(FileWriter writer = new FileWriter(new File(path))) {
+ writer.write(content);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/JdkInfo.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * It represents a JDK with some specific attributes.
+ * If two JdkInfo instances have the same version value, the instances are
+ * regarded as equivalent.
+ */
+public class JdkInfo {
+
+ public final String jdkPath;
+
+ public final String version;
+ public final boolean supportsECKey;
+ public final boolean supportsSNI;
+ public final boolean supportsALPN;
+
+ public JdkInfo(String jdkPath) throws Throwable {
+ this.jdkPath = jdkPath;
+
+ String output = jdkAttributes(jdkPath);
+ if (output == null || output.trim().isEmpty()) {
+ throw new RuntimeException(
+ "Cannot determine the JDK attributes: " + jdkPath);
+ }
+
+ String[] attributes = Utils.split(output, Utils.PARAM_DELIMITER);
+ version = attributes[0].replaceAll(".*=", "");
+ supportsECKey = Boolean.valueOf(attributes[1].replaceAll(".*=", ""));
+ supportsSNI = Boolean.valueOf(attributes[2].replaceAll(".*=", ""));
+ supportsALPN = Boolean.valueOf(attributes[3].replaceAll(".*=", ""));
+ }
+
+ // Determines the specific attributes for the specified JDK.
+ private static String jdkAttributes(String jdkPath) throws Throwable {
+ return ProcessUtils.java(jdkPath, null, JdkUtils.class).getOutput();
+ }
+
+ @Override
+ public int hashCode() {
+ return version == null ? 0 : version.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ JdkInfo other = (JdkInfo) obj;
+ if (version == null) {
+ if (other.version != null) {
+ return false;
+ }
+ } else if (!version.equals(other.version)) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean supportsCipherSuite(CipherSuite cipherSuite) {
+ JdkRelease jdkRelease = JdkRelease.getRelease(version);
+ return cipherSuite.startJdk.sequence <= jdkRelease.sequence
+ && (cipherSuite.endJdk == null
+ || cipherSuite.endJdk.sequence >= jdkRelease.sequence);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/JdkRelease.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * JDK major versions.
+ */
+public enum JdkRelease {
+
+ JDK6(6, "1.6"),
+ JDK7(7, "1.7"),
+ JDK8(8, "1.8"),
+ JDK9(9, "9"),
+ JDK10(10, "10");
+
+ public final int sequence;
+ public final String release;
+
+ private JdkRelease(int sequence, String release) {
+ this.sequence = sequence;
+ this.release = release;
+ }
+
+ public static JdkRelease getRelease(String jdkVersion) {
+ if (jdkVersion.startsWith(JDK6.release)) {
+ return JDK6;
+ } else if (jdkVersion.startsWith(JDK7.release)) {
+ return JDK7;
+ } else if (jdkVersion.startsWith(JDK8.release)) {
+ return JDK8;
+ } else if (jdkVersion.startsWith(JDK9.release)) {
+ return JDK9;
+ } else if (jdkVersion.startsWith(JDK10.release)) {
+ return JDK10;
+ }
+
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/JdkUtils.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.SSLParameters;
+
+/*
+ * This class is used for returning some specific JDK information.
+ */
+public class JdkUtils {
+
+ public static final String JAVA_RUNTIME_VERSION = "javaRuntimeVersion";
+ public static final String SUPPORTS_EC_KEY = "supportsECKey";
+ public static final String SUPPORTS_SNI = "supportsSNI";
+ public static final String SUPPORTS_ALPN = "supportsALPN";
+
+ // Returns the JDK build version.
+ public static String javaRuntimeVersion() {
+ return System.getProperty("java.runtime.version");
+ }
+
+ // Checks if EC key algorithm is supported by the JDK build.
+ private static boolean supportsECKey() {
+ boolean isSupported = true;
+ try {
+ KeyFactory.getInstance("EC");
+ } catch (NoSuchAlgorithmException e) {
+ isSupported = false;
+ }
+ return isSupported;
+ }
+
+ // Checks if SNI is supported by the JDK build.
+ private static boolean supportsSNI() {
+ boolean isSupported = true;
+ try {
+ SSLParameters.class.getMethod("getServerNames");
+ } catch (NoSuchMethodException e) {
+ isSupported = false;
+ }
+ return isSupported;
+ }
+
+ // Checks if ALPN is supported by the JDK build.
+ private static boolean supportsALPN() {
+ boolean isSupported = true;
+ try {
+ SSLParameters.class.getMethod("getApplicationProtocols");
+ } catch (NoSuchMethodException e) {
+ isSupported = false;
+ }
+ return isSupported;
+ }
+
+ public static void main(String[] args) {
+ System.out.print(Utils.join(Utils.PARAM_DELIMITER,
+ attr(JAVA_RUNTIME_VERSION, javaRuntimeVersion()),
+ attr(SUPPORTS_EC_KEY, supportsECKey()),
+ attr(SUPPORTS_SNI, supportsSNI()),
+ attr(SUPPORTS_ALPN, supportsALPN())));
+ }
+
+ private static String attr(String name, Object value) {
+ return name + "=" + String.valueOf(value);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Parameter.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * A tagging interface that all TLS communication parameters must implement.
+ */
+public interface Parameter { }
+
+/* The followings are TLS communication parameters. */
+
+enum Protocol implements Parameter {
+
+ SSLV3_0(3, "SSLv3"),
+ TLSV1_0(4, "TLSv1"),
+ TLSV1_1(5, "TLSv1.1"),
+ TLSV1_2(6, "TLSv1.2");
+
+ public final int sequence;
+ public final String version;
+
+ private Protocol(int sequence, String version) {
+ this.sequence = sequence;
+ this.version = version;
+ }
+
+ static Protocol getProtocol(String version) {
+ for (Protocol protocol : values()) {
+ if (protocol.version.equals(version)) {
+ return protocol;
+ }
+ }
+
+ return null;
+ }
+
+ static Protocol[] getMandatoryValues() {
+ return new Protocol[] { TLSV1_0, TLSV1_1, TLSV1_2 };
+ }
+}
+
+enum CipherSuite implements Parameter {
+
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_RSA_WITH_AES_256_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(),
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(),
+ TLS_RSA_WITH_AES_256_CBC_SHA(),
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(),
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(),
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA(),
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA(),
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_RSA_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK7),
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(),
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(),
+ TLS_RSA_WITH_AES_128_CBC_SHA(),
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(),
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(
+ Protocol.SSLV3_0, JdkRelease.JDK7),
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA(),
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA(),
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_RSA_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_RSA_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(
+ Protocol.TLSV1_2, JdkRelease.JDK8),
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA(),
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA(),
+ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA(),
+ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA(),
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA(),
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA(),
+ TLS_ECDH_ECDSA_WITH_RC4_128_SHA(),
+ TLS_ECDH_RSA_WITH_RC4_128_SHA(),
+ SSL_RSA_WITH_RC4_128_SHA(),
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA(),
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA(
+ Protocol.SSLV3_0, JdkRelease.JDK6),
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA(
+ Protocol.SSLV3_0, JdkRelease.JDK6),
+ SSL_RSA_WITH_RC4_128_MD5(
+ Protocol.SSLV3_0, JdkRelease.JDK6);
+
+ private static final boolean FULL_CIPHER_SUITES
+ = Utils.getBoolProperty("fullCipherSuites");
+
+ final Protocol startProtocol;
+ final Protocol endProtocol;
+
+ final JdkRelease startJdk;
+ final JdkRelease endJdk;
+
+ private CipherSuite(
+ Protocol startProtocol, Protocol endProtocol,
+ JdkRelease startJdk, JdkRelease endJdk) {
+ this.startProtocol = startProtocol;
+ this.endProtocol = endProtocol;
+
+ this.startJdk = startJdk;
+ this.endJdk = endJdk;
+ }
+
+ private CipherSuite(Protocol startProtocol, JdkRelease startJdk) {
+ this(startProtocol, null, startJdk, null);
+ }
+
+ private CipherSuite() {
+ this(Protocol.TLSV1_0, null, JdkRelease.JDK6, null);
+ }
+
+ boolean supportedByProtocol(Protocol protocol) {
+ return startProtocol.sequence <= protocol.sequence
+ && (endProtocol == null || endProtocol.sequence >= protocol.sequence);
+ }
+
+ static CipherSuite[] getMandatoryValues() {
+ return FULL_CIPHER_SUITES
+ ? values()
+ : new CipherSuite[] {
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS_RSA_WITH_AES_256_CBC_SHA256,
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 };
+ }
+
+ static CipherSuite getCipherSuite(String name) {
+ for (CipherSuite cipherSuite : values()) {
+ if (cipherSuite.name().equals(name)) {
+ return cipherSuite;
+ }
+ }
+
+ return null;
+ }
+}
+
+enum ClientAuth implements Parameter {
+
+ FALSE,
+ TRUE;
+
+ static ClientAuth[] getMandatoryValues() {
+ return new ClientAuth[] { TRUE };
+ }
+}
+
+enum ServerName implements Parameter {
+
+ NONE(null),
+ EXAMPLE("www.example.com");
+
+ final String name;
+
+ private ServerName(String name) {
+ this.name = name;
+ }
+
+ static ServerName[] getMandatoryValues() {
+ return new ServerName[] { EXAMPLE };
+ }
+}
+
+enum AppProtocol implements Parameter {
+
+ NONE(null, null),
+ EXAMPLE(new String[] { Utils.HTTP_2, Utils.HTTP_1_1 }, Utils.HTTP_2);
+
+ final String[] appProtocols;
+
+ // Expected negotiated application protocol
+ final String negoAppProtocol;
+
+ private AppProtocol(String[] appProtocols, String negoAppProtocol) {
+ this.appProtocols = appProtocols;
+ this.negoAppProtocol = negoAppProtocol;
+ }
+
+ static AppProtocol[] getMandatoryValues() {
+ return new AppProtocol[] { EXAMPLE };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/ProcessUtils.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * Utilities for executing java process.
+ */
+public class ProcessUtils {
+
+ private static final String TEST_CLASSES = System.getProperty("test.classes");
+
+ public static OutputAnalyzer java(String jdkPath, Map<String, String> props,
+ Class<?> clazz) {
+ List<String> cmds = new ArrayList<>();
+ cmds.add(jdkPath + "/bin/java");
+
+ if (props != null) {
+ for (Map.Entry<String, String> prop : props.entrySet()) {
+ cmds.add("-D" + prop.getKey() + "=" + prop.getValue());
+ }
+ }
+
+ cmds.add("-cp");
+ cmds.add(TEST_CLASSES);
+ cmds.add(clazz.getName());
+ try {
+ return ProcessTools.executeCommand(
+ cmds.toArray(new String[cmds.size()]));
+ } catch (Throwable e) {
+ throw new RuntimeException("Execute command failed: " + cmds, e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/README Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,130 @@
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# 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.
+
+##### Summary #####
+This test is used to check the interop compatibility on JSSE among different
+JDK releases. The oldest version supported by the test is JDK 6. Some of Java
+source files, JdkUtils.java, Parameter.java, Server.java, and Client.java, use
+only JDK 6-compliant language features and APIs, in order to allowing different
+JDK releases can load and run associated classes.
+
+##### Output #####
+The test can generate a report at $JTREG_WORKDIR/scratch/report.html to display
+the key information for each case. It also outputs all of details on both of
+server and client sides to a separated file at $JTREG_WORKDIR/scratch/test.html.
+
+##### Report Columns #####
+No.
+ A sequence number. It contains a hyper link to the corresponding details
+ in $JTREG_WORKDIR/scratch/test.html.
+
+ServerJDK
+ The version of the JDK that acts as server.
+
+ClientJDK
+ The version of the JDK that acts as client.
+
+Protocol
+ The TLS protocol version.
+
+CipherSuite
+ The only enabled cipher suite on both of server and client.
+
+ClientAuth
+ If the client authentication is checked, the value is "Y"; otherwise, "N".
+
+SNI
+ If the SNI is checked, the value is "Y"; otherwise, "N".
+
+ALPN
+ If the ALPN is checked, the value is "Y"; otherwise, "N".
+
+Status
+ It indicates the communication status for a test case.
+ There are three status:
+ SUCCESS: Communication succeed as expected.
+ UNEXPECTED_SUCCESS: Communication succeed as unexpected.
+ FAIL: Communication fails with unexpected failure.
+ EXPECTED_FAIL: Communication fails with expected failure.
+ Please note that, if a case finishes as status UNEXPECTED_SUCCESS or FAIL,
+ that means the case fails. Any failed case results in the test goes to fail.
+
+##### Usage #####
+jtreg [-options] \
+ [-Ddebug=<true|false>] \
+ [-DfullCases=<true|false>] \
+ [-DfullCipherSuites=<true|false>] \
+ [-DjdkListFile=</path/to/jdkListFile>] \
+ $JDK_WORKSPACE/test/jdk/javax/net/ssl/compatibility/Compatibility.java
+
+Besides the common jtreg options, like -jdk, this test introduces some more
+properties:
+debug
+ It indicates if the test enable -Djavax.net.ssl=debug. This is a boolean
+ property, and the default value is false.
+ It is not mandatory.
+
+fullCases
+ It indicates if testing the full or mandatory set of parameter values.
+ Every parameter provides a mandatory value set that must be covered.
+ For more details about the parameter value sets, please see Parameter.java.
+ This is a boolean property, and the default value is false.
+ It is not mandatory.
+
+fullCipherSuites
+ It indicates if testing the full or mandatory set of cipher suites.
+ For more details about the specific cipher suite sets, see CipherSuite in
+ Parameter.java.
+ This is a boolean property, and the default value is false.
+ It is not mandatory.
+
+jdkListFile
+ It indicate the path of a file, which lists the absolute paths of different
+ JDK builds. If no this property, the current testing JDK, specified by JTREG
+ option -jdk, is used as the testing JDK.
+ It is not mandatory.
+
+##### Usage Examples #####
+Example 1
+$ jtreg -jdk:/path/to/latest/jdk \
+ $JDK_WS/jdk/test/javax/net/ssl/compatibility/Compatibility.java
+This example doesn't specify any property introduced by the test. That means
+it uses the current testing JDK, namely /path/to/latest/jdk, as server and
+client. It doesn't output any debug log, and tests only mandatory parameter
+value sets.
+
+Example 2
+$ cat /path/to/jdkList
+/path/to/jdk6
+/path/to/jdk7
+/path/to/jdk8
+/path/to/jdk9
+/path/to/jdk10
+
+$ jtreg -jdk:/path/to/latest/jdk \
+ -Ddebug=true \
+ -DfullCipherSuites=true \
+ -DjdkListFile=/path/to/jdkList \
+ $JDK_WS/jdk/test/javax/net/ssl/compatibility/Compatibility.java
+The above example uses a file "/path/to/jdkList" to contain the paths of local
+different JDK builds through 6 to 10. The execution uses each of JDK builds as
+server and client respectively. And it enables SSL debug flag, and tests the
+full parameter value set.
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Server.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
+/*
+ * A simple SSL socket server.
+ */
+public class Server {
+
+ private final SSLServerSocket serverSocket;
+
+ public Server(SSLContext context, int port) throws Exception {
+ SSLServerSocketFactory serverFactory = context.getServerSocketFactory();
+ serverSocket = (SSLServerSocket) serverFactory.createServerSocket(port);
+ serverSocket.setSoTimeout(Utils.TIMEOUT);
+ }
+
+ public Server(Cert[] certs, int port) throws Exception {
+ this(Utils.createSSLContext(certs), port);
+ }
+
+ public Server(Cert[] certs) throws Exception {
+ this(certs, 0);
+ }
+
+ private void setEnabledCipherSuites(String... cipherSuites) {
+ serverSocket.setEnabledCipherSuites(cipherSuites);
+ }
+
+ private void setEnabledProtocols(String... protocols) {
+ serverSocket.setEnabledProtocols(protocols);
+ }
+
+ private void setNeedClientAuth(boolean needClientAuth) {
+ serverSocket.setNeedClientAuth(needClientAuth);
+ }
+
+ private void setApplicationProtocols(String... protocols) {
+ SSLParameters params = serverSocket.getSSLParameters();
+ params.setApplicationProtocols(protocols);
+ serverSocket.setSSLParameters(params);
+ }
+
+ public int getPort() {
+ return serverSocket.getLocalPort();
+ }
+
+ private void accept() throws IOException {
+ SSLSocket socket = null;
+ try {
+ socket = (SSLSocket) serverSocket.accept();
+
+ InputStream in = socket.getInputStream();
+ in.read();
+
+ OutputStream out = socket.getOutputStream();
+ out.write('S');
+ out.flush();
+ } finally {
+ if (socket != null) {
+ socket.close();
+ }
+ }
+ }
+
+ public void close() throws IOException {
+ serverSocket.close();
+ }
+
+ public static void main(String[] args) throws IOException {
+ System.out.println("----- Server start -----");
+ String protocol = System.getProperty(Utils.PROP_PROTOCOL);
+ String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
+ boolean clientAuth
+ = Utils.getBoolProperty(Utils.PROP_CLIENT_AUTH);
+ String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
+ boolean supportsALPN
+ = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
+ boolean negativeCase
+ = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_SERVER);
+
+ System.out.println(Utils.join(Utils.PARAM_DELIMITER,
+ "ServerJDK=" + System.getProperty(Utils.PROP_SERVER_JDK),
+ "Protocol=" + protocol,
+ "CipherSuite=" + cipherSuite,
+ "ClientAuth=" + clientAuth,
+ "AppProtocols=" + appProtocols));
+
+ Status status = Status.SUCCESS;
+ Server server = null;
+ try {
+ server = new Server(Cert.getCerts(cipherSuite));
+ System.out.println("port=" + server.getPort());
+ server.setNeedClientAuth(clientAuth);
+ server.setEnabledProtocols(protocol);
+ server.setEnabledCipherSuites(cipherSuite);
+ if (appProtocols != null) {
+ if (supportsALPN) {
+ server.setApplicationProtocols(
+ Utils.split(appProtocols, Utils.VALUE_DELIMITER));
+ } else {
+ System.out.println(
+ "Ignored due to server doesn't support ALPN.");
+ }
+ }
+
+ savePort(server.getPort());
+ server.accept();
+
+ status = negativeCase ? Status.UNEXPECTED_SUCCESS : Status.SUCCESS;
+ } catch (Exception exception) {
+ status = Utils.handleException(exception, negativeCase);
+ } finally {
+ if (server != null) {
+ server.close();
+ }
+
+ // Cleanups port.log.
+ File file = new File(Utils.PORT_LOG);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+
+ System.out.println("STATUS: " + status);
+ System.out.println("----- Server end -----");
+ }
+
+ private static void savePort(int port) throws IOException {
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(new File(Utils.PORT_LOG));
+ writer.write(port + "");
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Status.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 case result status.
+ */
+public enum Status {
+
+ SUCCESS, UNEXPECTED_SUCCESS, FAIL, EXPECTED_FAIL, TIMEOUT;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/TestCase.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * A test case for a specific TLS communication use case between two JDKs.
+ */
+public class TestCase {
+
+ public final JdkInfo serverJdk;
+ public final JdkInfo clientJdk;
+ public final UseCase useCase;
+
+ public final boolean negativeCaseOnServer;
+ public final boolean negativeCaseOnClient;
+
+ private Status status;
+
+ public TestCase(JdkInfo serverJdk, JdkInfo clientJdk, UseCase useCase) {
+ this.serverJdk = serverJdk;
+ this.clientJdk = clientJdk;
+ this.useCase = useCase;
+
+ negativeCaseOnServer = useCase.negativeCase
+ || !serverJdk.supportsCipherSuite(useCase.cipherSuite);
+ negativeCaseOnClient = useCase.negativeCase
+ || !clientJdk.supportsCipherSuite(useCase.cipherSuite);
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return Utils.join(Utils.PARAM_DELIMITER,
+ "ServerJDK=" + serverJdk.version,
+ "ClientJDK=" + clientJdk.version,
+ useCase.toString());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/UseCase.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * The TLS communication use case.
+ */
+public class UseCase {
+
+ private static final boolean FULL_CASES
+ = Utils.getBoolProperty("fullCases");
+
+ private static final Parameter[][] PARAMS = new Parameter[][] {
+ FULL_CASES ? Protocol.values() : Protocol.getMandatoryValues(),
+ FULL_CASES ? CipherSuite.values() : CipherSuite.getMandatoryValues(),
+ FULL_CASES ? ClientAuth.values() : ClientAuth.getMandatoryValues(),
+ FULL_CASES ? ServerName.values() : ServerName.getMandatoryValues(),
+ FULL_CASES ? AppProtocol.values() : AppProtocol.getMandatoryValues() };
+
+ public final Protocol protocol;
+ public final CipherSuite cipherSuite;
+ public final ClientAuth clientAuth;
+ public final ServerName serverName;
+ public final AppProtocol appProtocol;
+
+ public final boolean negativeCase;
+
+ public UseCase(
+ Protocol protocol,
+ CipherSuite cipherSuite,
+ ClientAuth clientAuth,
+ ServerName serverName,
+ AppProtocol appProtocol) {
+ this.protocol = protocol;
+ this.cipherSuite = cipherSuite;
+ this.clientAuth = clientAuth;
+ this.serverName = serverName;
+ this.appProtocol = appProtocol;
+
+ negativeCase = !cipherSuite.supportedByProtocol(protocol);
+ }
+
+ // JDK 6 doesn't support EC key algorithm.
+ public boolean ignoredByJdk(JdkInfo jdkInfo) {
+ return cipherSuite.name().contains("_EC") && !jdkInfo.supportsECKey;
+ }
+
+ @Override
+ public String toString() {
+ return Utils.join(Utils.PARAM_DELIMITER,
+ "Protocol=" + protocol.version,
+ "CipherSuite=" + cipherSuite,
+ "ClientAuth=" + clientAuth,
+ "ServerName=" + serverName,
+ "AppProtocols=" + appProtocol);
+ }
+
+ public static List<UseCase> getAllUseCases() {
+ List<UseCase> useCases = new ArrayList<>();
+ getUseCases(PARAMS, 0, new Parameter[PARAMS.length], useCases);
+ return useCases;
+ }
+
+ private static void getUseCases(Parameter[][] params, int index,
+ Parameter[] currentValues, List<UseCase> useCases) {
+ if (index == params.length) {
+ Protocol protocol = (Protocol) currentValues[0];
+ CipherSuite cipherSuite = (CipherSuite) currentValues[1];
+
+ UseCase useCase = new UseCase(
+ protocol,
+ cipherSuite,
+ (ClientAuth) currentValues[2],
+ (ServerName) currentValues[3],
+ (AppProtocol) currentValues[4]);
+ useCases.add(useCase);
+ } else {
+ Parameter[] values = params[index];
+ for (int i = 0; i < values.length; i++) {
+ currentValues[index] = values[i];
+ getUseCases(params, index + 1, currentValues, useCases);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Utils.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.IOException;
+import java.net.SocketTimeoutException;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.TrustManagerFactory;
+
+/*
+ * Utilities for testing.
+ */
+public class Utils {
+
+ /* ***** Properties ***** */
+ public static final String PROP_PORT = "test.port";
+ public static final String PROP_PROTOCOL = "test.protocol";
+ public static final String PROP_CIPHER_SUITE = "test.cipher.suite";
+ public static final String PROP_CLIENT_AUTH = "test.client.auth";
+ public static final String PROP_SERVER_JDK = "test.server.jdk";
+ public static final String PROP_CLIENT_JDK = "test.client.jdk";
+ public static final String PROP_SERVER_NAME = "test.server.name";
+ public static final String PROP_APP_PROTOCOLS
+ = "test.app.protocols";
+ public static final String PROP_NEGO_APP_PROTOCOL
+ = "test.negotiated.app.protocol";
+ public static final String PROP_SUPPORTS_SNI_ON_SERVER
+ = "test.supports.sni.on.server";
+ public static final String PROP_SUPPORTS_SNI_ON_CLIENT
+ = "test.supports.sni.on.client";
+ public static final String PROP_SUPPORTS_ALPN_ON_SERVER
+ = "test.supports.alpn.on.server";
+ public static final String PROP_SUPPORTS_ALPN_ON_CLIENT
+ = "test.supports.alpn.on.client";
+ public static final String PROP_NEGATIVE_CASE_ON_SERVER
+ = "test.negative.case.on.server";
+ public static final String PROP_NEGATIVE_CASE_ON_CLIENT
+ = "test.negative.case.on.client";
+
+ public static final int TIMEOUT = 10000;
+ public static final char[] PASSWORD = "testpass".toCharArray();
+
+ public static final String TEST_LOG = "test.html";
+ public static final String PORT_LOG = "port";
+
+ public static final String HTTP_2 = "h2";
+ public static final String HTTP_1_1 = "http/1.1";
+
+ public static final String PARAM_DELIMITER = ";";
+ public static final String VALUE_DELIMITER = ",";
+
+ /*
+ * Creates SSL context with the specified certificate.
+ */
+ public static SSLContext createSSLContext(Cert... certs) throws Exception {
+ KeyStore trustStore = KeyStore.getInstance("JKS");
+ trustStore.load(null, null);
+ for (int i = 0; i < certs.length; i++) {
+ trustStore.setCertificateEntry("trust-" + certs[i].name(),
+ createCert(certs[i]));
+ }
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+ tmf.init(trustStore);
+
+ KeyStore keyStore = KeyStore.getInstance("JKS");
+ keyStore.load(null, null);
+ for (int i = 0; i < certs.length; i++) {
+ PrivateKey privKey = createKey(certs[i]);
+ keyStore.setKeyEntry("cert-" + certs[i].name(), privKey, PASSWORD,
+ new Certificate[] { createCert(certs[i]) });
+ }
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+ kmf.init(keyStore, PASSWORD);
+
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ return context;
+ }
+
+ private static Certificate createCert(Cert cert) throws IOException {
+ try {
+ CertificateFactory certFactory
+ = CertificateFactory.getInstance("X.509");
+ return certFactory.generateCertificate(
+ new ByteArrayInputStream(cert.certMaterials.getBytes()));
+ } catch (Exception e) {
+ throw new RuntimeException("Create key failed: " + cert, e);
+ }
+ }
+
+ private static PrivateKey createKey(Cert cert)
+ throws NoSuchAlgorithmException, InvalidKeySpecException {
+ PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(
+ hexToBytes(cert.privKeyMaterials));
+ KeyFactory keyFactory = KeyFactory.getInstance(
+ getKeyAlgorithm(cert.signatureAlgorithm));
+ PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
+ return privKey;
+ }
+
+ private static String getKeyAlgorithm(
+ SignatureAlgorithm signatureAlgorithm) {
+ String signatureAlogrithmName = signatureAlgorithm.name();
+ return signatureAlogrithmName.equals(SignatureAlgorithm.ECDSA.name())
+ ? "EC"
+ : signatureAlogrithmName;
+ }
+
+ public static byte[] hexToBytes(String hex) {
+ if (hex == null) {
+ return null;
+ }
+
+ int length = hex.length();
+ if (length % 2 != 0) {
+ throw new IllegalArgumentException("Hex format is wrong.");
+ }
+
+ byte[] bytes = new byte[length / 2];
+ for (int i = 0; i < length; i += 2) {
+ bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ + Character.digit(hex.charAt(i + 1), 16));
+ }
+ return bytes;
+ }
+
+ public static String join(String delimiter, String... values) {
+ StringBuilder result = new StringBuilder();
+ if (values != null && values.length > 0) {
+ for (int i = 0; i < values.length - 1; i++) {
+ result.append(values[i]).append(delimiter);
+ }
+ result.append(values[values.length - 1]);
+ }
+ return result.toString();
+ }
+
+ public static String[] split(String str, String delimiter) {
+ return str == null ? new String[0] : str.split(delimiter);
+ }
+
+ public static String boolToStr(boolean bool) {
+ return bool ? "Y" : "N";
+ }
+
+ public static boolean getBoolProperty(String prop) {
+ return Boolean.valueOf(System.getProperty(prop));
+ }
+
+ public static Status handleException(Exception exception,
+ boolean negativeCase) {
+ Status status;
+ if ((exception instanceof SSLHandshakeException
+ || exception instanceof IllegalArgumentException)
+ && negativeCase) {
+ System.out.println("Expected exception: " + exception);
+ status = Status.EXPECTED_FAIL;
+ } else if (exception instanceof SocketTimeoutException) {
+ status = Status.TIMEOUT;
+ } else {
+ exception.printStackTrace(System.out);
+ status = Status.FAIL;
+ }
+ return status;
+ }
+
+ /* The HTML-related constants and methods. */
+
+ private static final String STYLE
+ = "style=\"font-family: Courier New; "
+ + "font-size: 12px; "
+ + "white-space: pre-wrap\"";
+
+ private static final String TABLE_STYLE
+ = "#test { font-family: \"Courier New\"; font-size: 12px; border-collapse: collapse; }\n"
+ + "#test td { border: 1px solid #ddd; padding: 4px; }\n"
+ + "#test tr:nth-child(odd) { background-color: #f2f2f2; }";
+
+ public static String row(Object... values) {
+ StringBuilder row = new StringBuilder();
+ row.append(startTr());
+ for (Object value : values) {
+ row.append(startTd());
+ row.append(value);
+ row.append(endTd());
+ }
+ row.append(endTr());
+ return row.toString();
+ }
+
+ public static String startHtml() {
+ return startTag("html");
+ }
+
+ public static String endHtml() {
+ return endTag("html");
+ }
+
+ public static String startPre() {
+ return startTag("pre " + STYLE);
+ }
+
+ public static String endPre() {
+ return endTag("pre");
+ }
+
+ public static String anchorName(String name, String text) {
+ return "<a name=" + name + ">" + text + "</a>";
+ }
+
+ public static String anchorLink(String file, String anchorName,
+ String text) {
+ return "<a href=" + file + "#" + anchorName + ">" + text + "</a>";
+ }
+
+ public static String tableStyle() {
+ return startTag("style") + TABLE_STYLE +endTag("style");
+ }
+
+ public static String startTable() {
+ return startTag("table id=\"test\"");
+ }
+
+ public static String endTable() {
+ return endTag("table");
+ }
+
+ private static String startTr() {
+ return startTag("tr");
+ }
+
+ private static String endTr() {
+ return endTag("tr");
+ }
+
+ private static String startTd() {
+ return startTag("td");
+ }
+
+ private static String endTd() {
+ return endTag("td");
+ }
+
+ private static String startTag(String tag) {
+ return "<" + tag + ">";
+ }
+
+ private static String endTag(String tag) {
+ return "</" + tag + ">";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/java.security Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,2 @@
+jdk.certpath.disabledAlgorithms=
+jdk.tls.disabledAlgorithms=
\ No newline at end of file
--- a/test/jdk/javax/sound/midi/Gervill/RiffReaderWriter/Close.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/javax/sound/midi/Gervill/RiffReaderWriter/Close.java Wed Nov 29 22:40:23 2017 +0100
@@ -22,6 +22,7 @@
*/
/* @test
+ @bug 8191384
@summary Test RiffReader close method
@modules java.desktop/com.sun.media.sound
*/
@@ -54,6 +55,8 @@
FileInputStream fis = new FileInputStream(tempfile);
reader = new RIFFReader(fis);
reader.close();
+ // second close should not throw any exceptions
+ reader.close();
reader = null;
}
finally
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/sound/sampled/spi/AudioFileReader/AudioInputStreamClose.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.spi.AudioFileReader;
+import javax.sound.sampled.spi.AudioFileWriter;
+
+import static java.util.ServiceLoader.load;
+import static javax.sound.sampled.AudioFileFormat.Type.AIFC;
+import static javax.sound.sampled.AudioFileFormat.Type.AIFF;
+import static javax.sound.sampled.AudioFileFormat.Type.AU;
+import static javax.sound.sampled.AudioFileFormat.Type.SND;
+import static javax.sound.sampled.AudioFileFormat.Type.WAVE;
+import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED;
+
+/**
+ * @test
+ * @bug 8191384
+ * @summary the stream returned by AudioFileReader should close its data stream
+ */
+public final class AudioInputStreamClose {
+
+ static final class StreamWrapper extends BufferedInputStream {
+
+ private boolean open = true;
+
+ StreamWrapper(final InputStream in) {
+ super(in);
+ }
+
+ @Override
+ public void close() throws IOException {
+ super.close();
+ open = false;
+ }
+
+ boolean isOpen() {
+ return open;
+ }
+ }
+
+ /**
+ * We will try to use all formats, in this case all our providers will be
+ * covered by supported/unsupported formats.
+ */
+ private static final List<AudioFormat> formats = new ArrayList<>(23000);
+
+ private static final AudioFormat.Encoding[] encodings = {
+ AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW,
+ AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED,
+ AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test")
+ };
+
+ private static final int[] sampleBits = {1, 4, 8, 11, 16, 20, 24, 32};
+
+ private static final int[] channels = {1, 2, 3, 4, 5};
+
+ private static final AudioFileFormat.Type[] types = {
+ WAVE, AU, AIFF, AIFC, SND,
+ new AudioFileFormat.Type("TestName", "TestExt")
+ };
+
+ private static final int FRAME_LENGTH = 10;
+
+ static {
+ for (final int sampleSize : sampleBits) {
+ for (final int channel : channels) {
+ for (final AudioFormat.Encoding enc : encodings) {
+ final int frameSize = ((sampleSize + 7) / 8) * channel;
+ formats.add(new AudioFormat(enc, 44100, sampleSize, channel,
+ frameSize, 44100, true));
+ formats.add(new AudioFormat(enc, 44100, sampleSize, channel,
+ frameSize, 44100, false));
+ }
+ }
+ }
+ }
+
+ public static void main(final String[] args) throws IOException {
+ for (final AudioFileWriter afw : load(AudioFileWriter.class)) {
+ for (final AudioFileReader afr : load(AudioFileReader.class)) {
+ for (final AudioFileFormat.Type type : types) {
+ for (final AudioFormat from : formats) {
+ test(afw, afr, type, getStream(from, true));
+ test(afw, afr, type, getStream(from, false));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Writes and reads the data to/from the stream.
+ */
+ private static void test(final AudioFileWriter afw,
+ final AudioFileReader afr,
+ final AudioFileFormat.Type type,
+ final AudioInputStream ais)
+ throws IOException {
+ try {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ afw.write(ais, type, out);
+ final InputStream input = new ByteArrayInputStream(out.toByteArray());
+ final StreamWrapper wrapper = new StreamWrapper(input);
+
+ // the wrapper should be closed as well
+ afr.getAudioInputStream(wrapper).close();
+
+ if (wrapper.isOpen()) {
+ System.err.println("Writer = " + afw);
+ System.err.println("Reader = " + afr);
+ throw new RuntimeException("Stream was not closed");
+ }
+ } catch (IOException | IllegalArgumentException |
+ UnsupportedAudioFileException ignored) {
+ }
+ }
+
+ private static AudioInputStream getStream(final AudioFormat format,
+ final boolean frameLength) {
+ final int dataSize = FRAME_LENGTH * format.getFrameSize();
+ byte[] buf = new byte[dataSize];
+ final InputStream in = new ByteArrayInputStream(buf);
+ if (frameLength) {
+ return new AudioInputStream(in, format, FRAME_LENGTH);
+ } else {
+ return new AudioInputStream(in, format, NOT_SPECIFIED);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/GraphicsConfigNotifier/TestMultiScreenGConfigNotify.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8178025
+ * @summary Verifies if graphicsConfiguration property notification is sent
+ * when frame is moved from one screen to another in multiscreen
+ * environment.
+ * @run main TestMultiScreenGConfigNotify
+ */
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+public class TestMultiScreenGConfigNotify {
+
+ static JFrame f;
+ static String propName[];
+ static int propCount = 0;
+ static boolean result = false;
+ public static void main(String[] args) throws Exception {
+
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice[] gds = ge.getScreenDevices();
+ if (gds.length < 2) {
+ return;
+ }
+ GraphicsConfiguration gc = gds[0].getDefaultConfiguration();
+ GraphicsConfiguration gc2 = gds[1].getDefaultConfiguration();
+ propName = new String[10];
+ SwingUtilities.invokeAndWait(() -> {
+ f = new JFrame();
+ f.setSize(300, 300);
+ f.setBounds(gc.getBounds().x, gc.getBounds().y, f.getWidth(), f.getHeight());
+ f.setVisible(true);
+
+ f.addPropertyChangeListener((PropertyChangeEvent evt) -> {
+ String name = evt.getPropertyName();
+ System.out.println("propertyChange " + name);
+ propName[propCount] = name;
+ propCount++;
+ });
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException ex) {
+ }
+ f.setBounds(gc2.getBounds().x, gc2.getBounds().y,
+ f.getWidth(), f.getHeight());
+ });
+
+ Thread.sleep(1000);
+ for(int i = 0; i < propCount; i++) {
+ if (propName[i].equals("graphicsConfiguration")) {
+ result = true;
+ }
+ }
+ SwingUtilities.invokeAndWait(() -> f.dispose());
+ if(!result) {
+ throw new RuntimeException("graphicsConfiguration notification not sent");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JButton/TestGlyphBreak.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8191428
+ * @summary Verifies if text view is not borken into multiple lines
+ * @run main/othervm -Dsun.java2d.uiScale=1.2 TestGlyphBreak
+ */
+
+import java.awt.FontMetrics;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+public class TestGlyphBreak {
+
+ static JFrame f;
+ static int btnHeight;
+ static FontMetrics fm;
+
+ public static void main(String[] args) throws Exception {
+
+ SwingUtilities.invokeAndWait(() -> {
+
+ String str = "<html><font size=2 color=red><bold>Three!</font></html>";
+ JButton b = new JButton();
+ b.setText(str);
+
+ f = new JFrame();
+ f.add(b);
+ f.pack();
+ f.setVisible(true);
+ btnHeight = b.getHeight();
+ fm = b.getFontMetrics(b.getFont());
+
+ });
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException ex) {
+ }
+ SwingUtilities.invokeAndWait(() -> f.dispose());
+ System.out.println("metrics getHeight " + fm.getHeight() +
+ " button height " + btnHeight);
+
+ // Check if text is broken into 2 lines, in which case button height
+ // will be twice the string height
+ if (btnHeight > 2*fm.getHeight()) {
+ throw new RuntimeException("TextView is broken into different lines");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JLabel/GetSpanHiDpiBug.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8178025
+ * @summary Verifies if SPANs in HTML text are rendered properly in hidpi
+ * @run main/manual/othervm -Dsun.java2d.uiScale=2.25 GetSpanHiDpiBug
+ */
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.beans.PropertyChangeSupport;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+public class GetSpanHiDpiBug {
+ public static void main(String[] args) throws Exception {
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ SpanTest test = new SpanTest(latch);
+ Thread T1 = new Thread(test);
+ T1.start();
+
+ // wait for latch to complete
+ boolean ret = false;
+ try {
+ ret = latch.await(3000, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ throw ie;
+ }
+ if (!ret) {
+ test.dispose();
+ throw new RuntimeException(" User has not executed the test");
+ }
+ if (test.testResult == false) {
+ throw new RuntimeException("Some characters overlap");
+ }
+ }
+}
+
+class SpanTest implements Runnable {
+ static JFrame f;
+ static JDialog dialog;
+ public boolean testResult = false;
+ private final CountDownLatch latch;
+
+ public SpanTest(CountDownLatch latch) throws Exception {
+ this.latch = latch;
+ }
+
+ @Override
+ public void run() {
+ try {
+ createUI();
+ spanTest();
+ } catch (Exception ex) {
+ dispose();
+ latch.countDown();
+ throw new RuntimeException("createUI Failed: " + ex.getMessage());
+ }
+ }
+
+ public void dispose() {
+ if (dialog != null) {
+ dialog.dispose();
+ }
+ if (f != null) {
+ f.dispose();
+ }
+ }
+
+ private static void spanTest() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ JLabel label =
+ new JLabel("<html><span>A few words to get started "
+ + "before the bug</span><span>overlapping text</span></html>");
+ f = new JFrame("");
+ f.getContentPane().add(label, BorderLayout.CENTER);
+ f.setSize(500,500);
+ f.setVisible(true);
+ }
+ });
+ }
+
+ private final void createUI() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ String description
+ = " INSTRUCTIONS:\n"
+ + " A string will be shown.\n "
+ + " Press Pass if there is no overlap of characters\n"
+ + " else press Fail.";
+
+ dialog = new JDialog();
+ dialog.setTitle("textselectionTest");
+ JTextArea textArea = new JTextArea(description);
+ textArea.setEditable(false);
+ final JButton passButton = new JButton("PASS");
+ passButton.addActionListener((e) -> {
+ testResult = true;
+ dispose();
+ latch.countDown();
+ });
+ final JButton failButton = new JButton("FAIL");
+ failButton.addActionListener((e) -> {
+ testResult = false;
+ dispose();
+ latch.countDown();
+ });
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(textArea, BorderLayout.CENTER);
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ buttonPanel.add(passButton);
+ buttonPanel.add(failButton);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialog.add(mainPanel);
+ dialog.pack();
+ dialog.setVisible(true);
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JMenu/8178430/LabelDotTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8178430
+ * @summary JMenu in GridBagLayout flickers when label text shows "..." and
+ * is updated
+ * @run main LabelDotTest
+ */
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Robot;
+
+import java.util.stream.IntStream;
+
+import javax.swing.SwingUtilities;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JFrame;
+import javax.swing.JMenuBar;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+public class LabelDotTest
+{
+ private final static String longText = "show a very long text to have it " +
+ "automatically shortened";
+ private final static String shortText = "show short text";
+
+ private static JFrame frame;
+ private static JLabel label;
+ private static JMenu menu;
+ private static volatile boolean isException = false;
+
+ private static void createUI() {
+ System.out.println("BEFORE CREATION");
+ frame = new JFrame();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(new Dimension(50, 150));
+ frame.setLocationRelativeTo(null);
+
+ frame.setLayout(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1.0;
+ c.weighty = 0.0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+
+ JMenuBar menuBar = new JMenuBar();
+ menu = new JMenu("Menu");
+ menuBar.add(menu);
+ frame.add(menuBar, c);
+
+ frame.add(new JLabel("Title", SwingConstants.CENTER), c);
+
+ c.weighty = 1.0;
+ frame.add(new JPanel(new GridBagLayout()), c);
+ c.weighty = 0.0;
+
+ label = new JLabel(shortText);
+ frame.add(label, c);
+
+ frame.setVisible(true);
+ }
+
+ private static void runTest(int iterations) throws Exception{
+ Robot robot = new Robot();
+
+ IntStream.range(0, iterations).forEach((i) -> {
+ SwingUtilities.invokeLater(() -> {
+ if (label.getText().equals(shortText)) {
+ label.setText(longText);
+ } else {
+ label.setText(shortText);
+ }
+ /* For a top level menu item, minimum size and the
+ preferred size should be the same, and should not be
+ equal to 1. Save the exception state and throw later
+ once the iterations are completed.
+ */
+ isException = (menu.getMinimumSize().height == 1 &&
+ !menu.getMinimumSize().equals(menu.getPreferredSize())) ||
+ isException;
+ });
+ robot.waitForIdle();
+ });
+ }
+
+ public static void main(String[] args) throws Exception {
+ try {
+ SwingUtilities.invokeAndWait(() -> createUI());
+ runTest(50);
+ } finally {
+ SwingUtilities.invokeAndWait(() -> frame.dispose());
+ if (isException)
+ throw new RuntimeException("Size of Menu bar is not correct.");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @key headful
+ * @bug 8176072
+ * @summary Checks whether reading attributes are obtained for Japanese IME
+ * @requires (os.family == "windows")
+ * @run main/manual JapaneseReadingAttributes
+ */
+
+/**
+ * This test requires a manual intervention as the keyboard layout has to be
+ * changed to Japanese IME. Once the keyboard layout has been selected, click on
+ * Start Test to start the automated tests. Will run two passes, first with an
+ * enter key in between to generate the yomigana for the first block of
+ * characters. The second without the intermediate enter key. Without the fix,
+ * there will be a mismatch in the reading attributes obtained.
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Robot;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+import java.awt.event.KeyEvent;
+import java.text.AttributedCharacterIterator;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
+
+public class JapaneseReadingAttributes {
+ private static boolean testPassed = false;
+ private static boolean startTest = false;
+
+ private static JFrame frame = null;
+ private static JLabel lblTestStatus = null;
+ private static JTextField textFieldMain = null;
+ private static JTextField textFieldReading = null;
+ private static String testResult;
+ private static String readingPass1;
+ private static String readingPass2;
+
+ private static final CountDownLatch testStartLatch = new CountDownLatch(1);
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ setupUI();
+ });
+
+ testStartLatch.await();
+
+ if (startTest) {
+ glyphTest();
+
+ frame.dispose();
+
+ if (testPassed) {
+ System.out.println(testResult);
+ } else {
+ throw new RuntimeException(testResult);
+ }
+ } else {
+ throw new RuntimeException("User has not executed the test");
+ }
+ }
+
+ private static void setupUI() {
+ String description = " 1. Go to \"Language Preferences -> Add a Language"
+ + "\" and add \"Japanese\"\n"
+ + " 2. Set current IM to \"Japanese\" \n"
+ + " 3. Try typing in the text field to ensure"
+ + " that Japanese IME has been successfully"
+ + " selected \n"
+ + " 4. Now click on \"Start Test\" button \n";
+ String title = "Reading Attributes test Japanese IME (Windows)";
+
+ frame = new JFrame(title);
+
+ JPanel mainPanel = new JPanel(new BorderLayout());
+
+ JPanel textEditPanel = new JPanel(new FlowLayout());
+
+ textFieldMain = new JTextField(20);
+
+ textFieldReading = new JTextField(20);
+ textFieldReading.setEditable(false);
+
+ textEditPanel.add(textFieldMain);
+ textEditPanel.add(textFieldReading);
+
+ mainPanel.add(textEditPanel, BorderLayout.CENTER);
+
+ JTextArea textArea = new JTextArea(description);
+ textArea.setEditable(false);
+ final JButton btnStartTest = new JButton("Start Test");
+ final JButton btnCancelTest = new JButton("Cancel Test");
+
+ btnStartTest.addActionListener((e) -> {
+ btnStartTest.setEnabled(false);
+ btnCancelTest.setEnabled(false);
+ startTest = true;
+ testStartLatch.countDown();
+ });
+
+ btnCancelTest.addActionListener((e) -> {
+ frame.dispose();
+ testStartLatch.countDown();
+ });
+ mainPanel.add(textArea, BorderLayout.NORTH);
+
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ buttonPanel.add(btnStartTest);
+ buttonPanel.add(btnCancelTest);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+
+ lblTestStatus = new JLabel("");
+ lblTestStatus.setMinimumSize(new Dimension(250, 20));
+ lblTestStatus.setPreferredSize(new Dimension(250, 20));
+ lblTestStatus.setVisible(true);
+ textEditPanel.add(lblTestStatus);
+
+ frame.add(mainPanel);
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ frame.pack();
+ frame.setLocationRelativeTo(null);
+
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ testStartLatch.countDown();
+ }
+ @Override
+ public void windowOpened( WindowEvent e ){
+ textFieldMain.requestFocusInWindow();
+ }
+ });
+
+ textFieldMain.addInputMethodListener(new InputMethodListener() {
+ @Override
+ public void caretPositionChanged(InputMethodEvent event) {
+ }
+
+ @Override
+ public void inputMethodTextChanged(InputMethodEvent event) {
+ AttributedCharacterIterator itr = event.getText();
+ if (itr != null) {
+ int toCopy = event.getCommittedCharacterCount();
+ if (toCopy > 0) {
+ itr.first();
+ StringBuilder yomigana = new StringBuilder(
+ textFieldReading.getText());
+ while (toCopy-- > 0) {
+ if (itr.getIndex() == itr.getRunStart(
+ AttributedCharacterIterator.Attribute.READING)) {
+ java.text.Annotation annotatedText
+ = (java.text.Annotation) itr.
+ getAttribute(AttributedCharacterIterator.Attribute.READING);
+ yomigana.append(annotatedText.getValue());
+ }
+ itr.next();
+ }
+ textFieldReading.setText(yomigana.toString());
+ }
+ }
+ }
+ });
+
+ frame.setVisible(true);
+ }
+
+ private static void glyphTest() throws Exception {
+ Robot robotKeySimulator = new Robot();
+ performTasks(robotKeySimulator);
+ }
+
+ public static void performTasks(Robot robotForKeyInput) throws Exception {
+ lblTestStatus.setText("Running Tests..");
+ robotForKeyInput.setAutoDelay(500);
+
+ ArrayList<Integer> keyCodesToUse = new ArrayList<Integer>();
+
+ keyCodesToUse.add(KeyEvent.VK_A);
+ keyCodesToUse.add(KeyEvent.VK_B);
+ keyCodesToUse.add(KeyEvent.VK_E);
+ keyCodesToUse.add(KeyEvent.VK_SPACE);
+ keyCodesToUse.add(KeyEvent.VK_SPACE);
+ keyCodesToUse.add(KeyEvent.VK_ENTER);
+ keyCodesToUse.add(KeyEvent.VK_S);
+ keyCodesToUse.add(KeyEvent.VK_I);
+ keyCodesToUse.add(KeyEvent.VK_N);
+ keyCodesToUse.add(KeyEvent.VK_Z);
+ keyCodesToUse.add(KeyEvent.VK_O);
+ keyCodesToUse.add(KeyEvent.VK_U);
+ keyCodesToUse.add(KeyEvent.VK_SPACE);
+ keyCodesToUse.add(KeyEvent.VK_ENTER);
+
+ textFieldMain.requestFocusInWindow();
+
+ robotForKeyInput.waitForIdle();
+
+ enterInput(robotForKeyInput, keyCodesToUse);
+
+ SwingUtilities.invokeAndWait(() -> {
+ readingPass1 = textFieldReading.getText();
+ });
+
+ if (setTaskStatus(readingPass1, 1)) {
+ keyCodesToUse.remove((Integer) KeyEvent.VK_ENTER);
+
+ enterInput(robotForKeyInput, keyCodesToUse);
+
+ SwingUtilities.invokeAndWait(() -> {
+ readingPass2 = textFieldReading.getText();
+ });
+
+ if (setTaskStatus(readingPass2, 2)) {
+ if (readingPass1.equals(readingPass2)) {
+ testPassed = true;
+ testResult = "Test Passed : Same reading attribute "
+ + "obtained from both passes ";
+ lblTestStatus.setText(testResult);
+ } else {
+ testResult = "Test Failed : Reading attribute from Pass 1 <"
+ + readingPass1 + "> != Reading attribute "
+ + "from Pass 2 <" + readingPass2 + ">";
+ }
+ }
+ }
+ }
+
+ private static void enterInput(Robot robotKeyInput,
+ ArrayList<Integer> keyInputs) {
+ textFieldReading.setText("");
+ textFieldMain.setText("");
+
+ String strKeyInput = "KeyPress=>";
+ int nOfKeyInputs = keyInputs.size();
+ for (int i = 0; i < nOfKeyInputs; i++) {
+ int keyToUse = keyInputs.get(i);
+ robotKeyInput.keyPress(keyToUse);
+ robotKeyInput.keyRelease(keyToUse);
+ strKeyInput += (Integer.toHexString(keyToUse)) + ":";
+ }
+
+ System.out.println(strKeyInput);
+ }
+
+ public static boolean setTaskStatus(String readingValue, int passCount) {
+ boolean status = false;
+
+ if (!readingValue.isEmpty()) {
+ testResult = "Attribute : " + readingValue
+ + "read from pass " + Integer.toString(passCount);
+ status = true;
+ } else {
+ testResult = "Failed to read Reading attribute from pass "
+ + Integer.toString(passCount);
+ }
+
+ lblTestStatus.setText(testResult);
+
+ return status;
+ }
+}
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java Wed Nov 29 22:40:23 2017 +0100
@@ -33,12 +33,13 @@
* @library ../../../../lib/testlibrary
* @build Common ExtendedRobot
* @run main PerPixelTranslucentCanvas
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 PerPixelTranslucentCanvas
*/
public class PerPixelTranslucentCanvas extends Common {
JPanel center;
- Color OVAL_COLOR = Color.BLUE;
+ static Color OVAL_COLOR = Color.BLUE;
public static void main(String[] ignored) throws Exception {
FG_COLOR = new Color(200, 0, 0, 100);
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java Wed Nov 29 22:40:23 2017 +0100
@@ -90,7 +90,7 @@
Color color = robot.getPixelColor(loc.x + bounds.width / 2, loc.y + bounds.height + 3);
System.out.println(color);
- if (FG_COLOR.getRGB() == color.getRGB())
+ if (BG_COLOR.getRGB() != color.getRGB())
throw new RuntimeException("Background is not translucent (" + color + ")");
EventQueue.invokeAndWait(this::dispose);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/event/EventListenerList/GetUpToDateData.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.awt.event.AWTEventListener;
+import java.util.EventListener;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.event.EventListenerList;
+
+/**
+ * @test
+ * @bug 5031664
+ * @summary EventListenerList.getXXX should always return up to date data
+ */
+public final class GetUpToDateData {
+
+ static final EventListenerList listeners = new EventListenerList();
+
+ static final EventListener o1 = new EventListener() {
+ };
+ static final AWTEventListener o2 = event -> {
+ };
+
+ public static void main(final String[] args) throws Exception {
+ CountDownLatch go = new CountDownLatch(3);
+
+ Thread t1 = new Thread(() -> {
+ try {
+ // Time to warm-up t3, t4, t5
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ }
+ listeners.add(EventListener.class, o1);
+ });
+ Thread t2 = new Thread(() -> {
+ try {
+ // Time to warm-up t3, t4, t5
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ }
+ listeners.add(AWTEventListener.class, o2);
+ });
+
+ Thread t3 = new Thread(() -> {
+ while (listeners.getListenerCount() != 2) {
+ }
+ go.countDown();
+ });
+ Thread t4 = new Thread(() -> {
+ while (listeners.getListeners(EventListener.class).length != 1
+ || listeners.getListeners(EventListener.class)[0] != o1) {
+ }
+ go.countDown();
+ });
+ Thread t5 = new Thread(() -> {
+ while (listeners.getListeners(AWTEventListener.class).length != 1
+ || listeners.getListeners(AWTEventListener.class)[0] != o2) {
+ }
+ go.countDown();
+ });
+
+ t1.setDaemon(true);
+ t2.setDaemon(true);
+ t3.setDaemon(true);
+ t4.setDaemon(true);
+ t5.setDaemon(true);
+
+ t1.start();
+ t2.start();
+ t3.start();
+ t4.start();
+ t5.start();
+ if (!go.await(10, TimeUnit.SECONDS)) {
+ throw new RuntimeException("The test hangs");
+ }
+ }
+}
--- a/test/jdk/sanity/client/SwingSet/src/SliderDemoTest.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/sanity/client/SwingSet/src/SliderDemoTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -82,6 +82,7 @@
JSliderOperator jso = new JSliderOperator(jfo,
new AccessibleNameChooser(accessibleName));
if (accessibleName.equals(HORIZONTAL_PLAIN_SLIDER)) {
+ jso.waitHasFocus();
checkKeyboard(jso);
checkMouse(jso);
}
--- a/test/jdk/sun/java2d/SunGraphics2D/DrawImageBilinear.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/sun/java2d/SunGraphics2D/DrawImageBilinear.java Wed Nov 29 22:40:23 2017 +0100
@@ -23,11 +23,12 @@
/*
* @test
* @key headful
- * @bug 5009033 6603000 6666362
+ * @bug 5009033 6603000 6666362 8159142
* @summary Verifies that images transformed with bilinear filtering do not
* leave artifacts at the edges.
- * @run main/othervm DrawImageBilinear
- * @run main/othervm -Dsun.java2d.opengl=True DrawImageBilinear
+ * @run main/othervm -Dsun.java2d.uiScale=2.5 DrawImageBilinear
+ * @run main/othervm -Dsun.java2d.uiScale=2.5 -Dsun.java2d.opengl=True DrawImageBilinear
+ * @run main/othervm -Dsun.java2d.uiScale=2.5 -Dsun.java2d.d3d=false DrawImageBilinear
* @author campbelc
*/
--- a/test/jdk/tools/jar/multiRelease/Basic.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/tools/jar/multiRelease/Basic.java Wed Nov 29 22:40:23 2017 +0100
@@ -23,6 +23,7 @@
/*
* @test
+ # @bug 8186087
* @library /test/lib
* @modules java.base/jdk.internal.misc
* jdk.compiler
@@ -346,39 +347,6 @@
}
@Test
- // resources with same name in different versions
- // this is okay but produces warning
- public void test08() throws Throwable {
- String jarfile = "test.jar";
-
- compile("test01"); //use same data as test01
-
- Path classes = Paths.get("classes");
-
- // add a resource to the base
- Path source = Paths.get(src, "data", "test01", "base", "version");
- Files.copy(source.resolve("Version.java"), classes.resolve("base")
- .resolve("version").resolve("Version.java"));
-
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
- "--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .shouldHaveExitValue(SUCCESS)
- .shouldBeEmpty();
-
- // now add a different resource with same name to META-INF/version/9
- Files.copy(source.resolve("Main.java"), classes.resolve("v9")
- .resolve("version").resolve("Version.java"));
-
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
- "--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .shouldHaveExitValue(SUCCESS)
- .shouldContain("multiple resources with same name");
-
- FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
- FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
- }
-
- @Test
// a class with an internal name different from the external name
public void test09() throws Throwable {
String jarfile = "test.jar";
@@ -451,7 +419,9 @@
.shouldNotHaveExitValue(SUCCESS)
.asLines();
+ /* "META-INF/versions/9/version/Nested$nested.class" is really NOT isolated
assertTrue(output.size() == 4);
+ assertTrue(output.size() == 3);
assertTrue(output.get(0).contains("an isolated nested class"),
output.get(0));
assertTrue(output.get(1).contains("contains a new public class"),
@@ -460,6 +430,17 @@
output.get(2));
assertTrue(output.get(3).contains("invalid multi-release jar file"),
output.get(3));
+ assertTrue(output.get(2).contains("invalid multi-release jar file"),
+ output.get(2));
+ */
+
+ assertTrue(output.size() == 3);
+ assertTrue(output.get(0).contains("an isolated nested class"),
+ output.get(0));
+ assertTrue(output.get(1).contains("contains a new public class"),
+ output.get(1));
+ assertTrue(output.get(2).contains("invalid multi-release jar file"),
+ output.get(2));
FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
@@ -495,6 +476,31 @@
}
@Test
+ // assure the nested-nested classes are acceptable
+ public void test13() throws Throwable {
+ String jarfile = "test.jar";
+
+ compile("test01"); //use same data as test01
+
+ Path classes = Paths.get("classes");
+
+ // add a base class with a nested and nested-nested class
+ Path source = Paths.get(src, "data", "test13", "base", "version");
+ javac(classes.resolve("base"), source.resolve("Nested.java"));
+
+ // add a versioned class with a nested and nested-nested class
+ source = Paths.get(src, "data", "test13", "v10", "version");
+ javac(classes.resolve("v10"), source.resolve("Nested.java"));
+
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
+ }
+
+ @Test
public void testCustomManifest() throws Throwable {
String jarfile = "test.jar";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jar/multiRelease/data/test13/base/version/Nested.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,22 @@
+package version;
+
+public class Nested {
+ public int getVersion() {
+ return 9;
+ }
+
+ protected void doNothing() {
+ }
+
+ private void anyName() {
+ }
+
+ class nested {
+ int save;
+
+ class nestnested {
+ int save;
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jar/multiRelease/data/test13/v10/version/Nested.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,18 @@
+package version;
+
+public class Nested {
+ public int getVersion() {
+ return 10;
+ }
+
+ protected void doNothing() {
+ }
+
+ class nested {
+ int save = getVersion();
+
+ class nestnested {
+ int save = getVersion();;
+ }
+ }
+}
--- a/test/jdk/tools/jar/multiRelease/whitebox/jdk.jartool/sun/tools/jar/ValidatorComparatorTest.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/jdk/tools/jar/multiRelease/whitebox/jdk.jartool/sun/tools/jar/ValidatorComparatorTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -29,7 +29,7 @@
import java.util.List;
import static java.util.stream.Collectors.toList;
-import static sun.tools.jar.Validator.ENTRYNAME_COMPARATOR;
+import static sun.tools.jar.Main.ENTRYNAME_COMPARATOR;
import org.testng.Assert;
import org.testng.annotations.Test;
--- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java Wed Nov 29 22:40:23 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363 8160196 8151743 8177417
- * 8175218 8176452 8181215 8182263 8183511 8169819 8183037
+ * 8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369
* @summary Run tests on doclet stylesheet.
* @author jamieh
* @library ../lib
@@ -50,16 +50,6 @@
// TODO: most of this test seems a bit silly, since javadoc is simply
// copying in the stylesheet from the source directory
checkOutput("stylesheet.css", true,
- "/* Javadoc style sheet */",
- "/*\n"
- + "Overall document style\n"
- + "*/",
- "/*\n"
- + "Heading styles\n"
- + "*/",
- "/*\n"
- + "Navigation bar styles\n"
- + "*/",
"body {\n"
+ " background-color:#ffffff;\n"
+ " color:#353833;\n"
@@ -173,8 +163,8 @@
+ " position:relative;\n"
+ " padding-top:129px;\n"
+ " margin-top:-129px;\n"
- + "}\n"
- + ".searchTagResult:before, .searchTagResult:target {\n"
+ + "}",
+ ".searchTagResult:before, .searchTagResult:target {\n"
+ " color:red;\n"
+ "}",
"a[href]:hover, a[href]:focus {\n"
--- a/test/langtools/jdk/jshell/ForwardReferenceImportTest.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/jdk/jshell/ForwardReferenceImportTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -188,7 +188,7 @@
DiagCheck.DIAG_ERROR,
added(VALID),
ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
- assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.static.single.import");
+ assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.single.import");
assertActiveKeys();
assertDrop(list,
ste(list, VALID, DROPPED, true, null),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/jshell/InaccessibleExpressionTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8190939
+ * @summary test expressions whose type is inaccessible
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.jdeps/com.sun.tools.javap
+ * @library /tools/lib
+ * @build KullaTesting Compiler
+ * @run testng InaccessibleExpressionTest
+ */
+
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.testng.annotations.BeforeMethod;
+import jdk.jshell.VarSnippet;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+@Test
+public class InaccessibleExpressionTest extends KullaTesting {
+
+ @BeforeMethod
+ @Override
+ public void setUp() {
+ Path path = Paths.get("eit");
+ Compiler compiler = new Compiler();
+ compiler.compile(path,
+ "package priv;\n" +
+ "\n" +
+ "import java.util.function.Supplier;\n" +
+ "import java.util.ArrayList;\n" +
+ "\n" +
+ "public class GetPriv {\n" +
+ " private enum Count { One };\n" +
+ " public static Packp down() { return new Packp(); }\n" +
+ " public static MyList list() { return new MyList(); }\n" +
+ " public static Count priv() { return Count.One; }\n" +
+ "}\n" +
+ "\n" +
+ "class Packp extends Packp2 {\n" +
+ "public String toString() { return \"Packp\"; } }\n" +
+ "\n" +
+ "class Packp2 implements Supplier<Integer> {" +
+ "public Integer get() { return 5; }}\n" +
+ "\n" +
+ "class MyList extends ArrayList<Integer> {}");
+ String tpath = compiler.getPath(path).toString();
+ setUp(b -> b
+ .remoteVMOptions("--class-path", tpath)
+ .compilerOptions("--class-path", tpath));
+ }
+
+ public void testExternal() {
+ assertEval("import static priv.GetPriv.*;");
+ VarSnippet down = varKey(assertEval("down()", "Packp"));
+ assertEquals(down.typeName(), "priv.Packp");
+ assertEval(down.name() + ".get()", "5");
+ VarSnippet list = varKey(assertEval("list()", "[]"));
+ assertEquals(list.typeName(), "priv.MyList");
+ assertEval(list.name() + ".size()", "0");
+ VarSnippet one = varKey(assertEval("priv()", "One"));
+ assertEquals(one.typeName(), "priv.GetPriv.Count");
+ }
+
+ public void testInternal() {
+ assertEval(
+ "class Top {" +
+ " private class Inner {" +
+ " public String toString() { return \"Inner\"; }" +
+ " }" +
+ " Inner n = new Inner(); }");
+ VarSnippet n = varKey(assertEval("new Top().n", "Inner"));
+ assertEquals(n.typeName(), "Top.Inner");
+ }
+
+}
--- a/test/langtools/jdk/jshell/TypeNameTest.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/jdk/jshell/TypeNameTest.java Wed Nov 29 22:40:23 2017 +0100
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8144903 8171981
+ * @bug 8144903 8171981 8191802
* @summary Tests for determining the type from the expression
* @build KullaTesting TestingInputStream
* @run testng TypeNameTest
@@ -55,7 +55,7 @@
assertEval("class D<T extends CharSequence> { D<? super T> getS() { return null; } }");
assertEval("D<?> d = new D<String>();");
- assertType("d.getS()", "D<? extends CharSequence>");
+ assertType("d.getS()", "D<?>");
assertType("null", "Object");
assertType("Class.forName( \"java.util.ArrayList\" )", "Class<?>");
assertType("new ArrayList<Boolean>() {}", "ArrayList<Boolean>");
@@ -68,7 +68,7 @@
assertEval("interface J extends A, I {}");
assertEval("interface K extends A, I {}");
assertEval("class P<T extends A & I> {}");
- assertType("(P<?>) null", "P<? extends Object>");
+ assertType("(P<?>) null", "P<?>");
}
public void testConditionals() {
--- a/test/langtools/tools/javac/4980495/std/NonStatic2StaticImportClash.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/tools/javac/4980495/std/NonStatic2StaticImportClash.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,14 +1,14 @@
/*
* @test /nodynamiccopyright/
- * @bug 7101822
+ * @bug 7101822 8133616
* @summary Check the when clashing types are imported through an ordinary and static import,
* the compile-time error is properly reported.
* @compile/fail/ref=NonStatic2StaticImportClash.out -XDrawDiagnostics NonStatic2StaticImportClash.java p1/A1.java p2/A2.java
*
*/
-import p1.A1.f;
-import static p2.A2.f;
+import static p1.A1.f;
+import p2.A2.f;
public class NonStatic2StaticImportClash {
}
--- a/test/langtools/tools/javac/4980495/std/Static2NonStaticImportClash.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/tools/javac/4980495/std/Static2NonStaticImportClash.java Wed Nov 29 22:40:23 2017 +0100
@@ -1,14 +1,14 @@
/*
* @test /nodynamiccopyright/
- * @bug 7101822
+ * @bug 7101822 8133616
* @summary Check the when clashing types are imported through an ordinary and static import,
* the compile-time error is properly reported.
* @compile/fail/ref=Static2NonStaticImportClash.out -XDrawDiagnostics Static2NonStaticImportClash.java p1/A1.java p2/A2.java
*
*/
-import static p2.A2.f;
-import p1.A1.f;
+import p2.A2.f;
+import static p1.A1.f;
public class Static2NonStaticImportClash {
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/analyzer/LambdaWithMethod.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,17 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8191981
+ * @compile/fail/ref=LambdaWithMethod.out -Werror -XDrawDiagnostics -XDfind=lambda LambdaWithMethod.java
+ */
+
+public class LambdaWithMethod {
+ public static void run(Runnable r) {
+ run(new Runnable() {
+ public void run() {
+ put(get());
+ }
+ });
+ }
+ private static String get() { return null; }
+ private static void put(String i) {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/analyzer/LambdaWithMethod.out Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,4 @@
+LambdaWithMethod.java:9:28: compiler.warn.potential.lambda.found
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/test/langtools/tools/javac/diags/examples/AlreadyDefinedStaticImport/AlreadDefinedStaticImport.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/AlreadyDefinedStaticImport/AlreadDefinedStaticImport.java Wed Nov 29 22:40:23 2017 +0100
@@ -23,5 +23,5 @@
// key: compiler.err.already.defined.static.single.import
-import p.E1.A;
-import static p.E2.A;
+import static p.E1.A;
+import p.E2.A;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/generics/inference/8178427/T8178427.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8178427
+ * @summary NPE in Infer$CheckUpperBounds
+ * @compile T8178427.java
+ */
+
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.function.*;
+import java.util.stream.*;
+
+abstract class X {
+ public interface N<K, V> {
+ Stream<V> getValues();
+ }
+
+ abstract <K, V> N<K, V> c();
+
+ abstract <T, K, V, M extends N<K, V>> Collector<T, ?, M> f(
+ Function<? super T, ? extends K> k,
+ Function<? super T, ? extends Stream<? extends V>> v,
+ Supplier<M> multimapSupplier);
+
+ void m(Map<String, N<?, ?>> c, ExecutorService s) {
+ s.submit(() -> {
+ return c.entrySet().parallelStream()
+ .collect(f(Map.Entry::getKey, e -> e.getValue().getValues(), this::c));
+ });
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lvti/T8191893.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8191802 8191893
+ * @summary Upward projection result is A<? extends Number> instead of A<? super Integer>
+ * @compile T8191893.java
+ */
+
+class T8191893 {
+
+ static class A<E> { }
+
+ <T> A<? super T> m(T t) {
+ return null;
+ }
+
+ <U> A<? super A<? super U>> m2(A<? super U> u) {
+ return null;
+ }
+
+ void test() {
+ var varValue = m2(m(10));
+ A<? super A<Object>> expectedTypeValue = varValue;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lvti/T8191959.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8191802 8191959
+ * @summary Upward projection result is A<? extends Number> instead of A<? super Integer>
+ * @compile T8191959.java
+ */
+
+public class T8191959 {
+ static class A<E> { }
+
+ <T> A<? super T> m(T t) {
+ return null;
+ }
+
+ <U> A<? super A<? extends U>> m2(A<? super U> u) {
+ return null;
+ }
+
+ void test() {
+ var varValue = m2(m(10));
+ A<? super A<? extends Integer>> expectedTypeValue = varValue;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lvti/TestBadArray.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8191802
+ * @summary Upward projection result is A<? extends Number> instead of A<? super Integer>
+ * @compile TestBadArray.java
+ */
+
+import java.util.List;
+
+class TestArr {
+ <Z> List<? super Z[]> m(List<Z> z) { return null; }
+ void test(List<? extends Number> l) {
+ var v = m(l);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lvti/harness/UpperBounds.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8191802
+ * @summary Upward projection result is A<? extends Number> instead of A<? super Integer>
+ * @modules jdk.compiler/com.sun.source.tree
+ * jdk.compiler/com.sun.source.util
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build LocalVariableInferenceTester
+ * @run main LocalVariableInferenceTester UpperBounds.java
+ */
+class UpperBounds {
+
+ static class A<T extends Number> { }
+
+ static class C<T extends Comparable<T>> { }
+
+ void test1(A<? super Integer> s) {
+ //U is not Object, Bi is not fbound and U is not more specific than Bi, use "? super L"
+ @InferredType("UpperBounds.A<? super java.lang.Integer>")
+ var x = s;
+ }
+
+ void test2(C<? super Integer> s) {
+ //U is not Object, Bi is fbound, use "? extends L"
+ @InferredType("UpperBounds.C<? extends java.lang.Comparable<?>>")
+ var x = s;
+ }
+
+ void test3(A<? extends Object> s) {
+ //U is not Object, Bi is not fbound and U is not more specific than Bi, L is undefined, use "?"
+ @InferredType("UpperBounds.A<?>")
+ var x = s;
+ }
+
+ void test4(A<? extends Integer> s) {
+ //U is not Object, Bi is not fbound and U is more specific than Bi, use "? extends U"
+ @InferredType("UpperBounds.A<? extends java.lang.Integer>")
+ var x = s;
+ }
+
+ void test5(A<? extends Object> s) {
+ //U is not Object, Bi is not fbound and U is not more specific than Bi, L is undefined, use "?"
+ @InferredType("UpperBounds.A<?>")
+ var x = s;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/util/TestTypeKindVisitors.java Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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 8191234
+ * @summary Test TypeKind visitors on pseudo types.
+ * @library /tools/javac/lib
+ * @modules java.compiler
+ * @build JavacTestingAbstractProcessor TestTypeKindVisitors
+ * @compile -processor TestTypeKindVisitors -proc:only TestTypeKindVisitors.java
+ */
+
+import java.lang.annotation.Annotation;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import static javax.lang.model.SourceVersion.*;
+
+public class TestTypeKindVisitors extends JavacTestingAbstractProcessor {
+ @Override
+ public boolean process(Set<? extends TypeElement> tes,
+ RoundEnvironment round) {
+ if (round.processingOver())
+ return true;
+
+ List<NoType> tradNoTypes = List.of(types.getNoType(TypeKind.NONE),
+ types.getNoType(TypeKind.VOID),
+ getPackageNoType());
+ NoType moduleNoType = getModuleNoType();
+
+ // For KindVisitors based on 6, 7, and 8
+ for (TypeVisitor<TypeKind, String> visitor : getVisitors()) {
+ System.out.println(visitor.getClass().getSuperclass().getName());
+
+ for (NoType noType : tradNoTypes) {
+ System.out.println("\t" + noType.toString());
+ checkTypeKind(noType.getKind(), visitor.visit(noType));
+ }
+
+ if (RELEASE_9.compareTo(visitor.getClass().getSuperclass().
+ getAnnotation(SupportedSourceVersion.class).
+ value()) > 0) {
+ try {
+ System.out.println("\t" + moduleNoType.toString());
+ visitor.visit(moduleNoType);
+ } catch (UnknownTypeException ute) {
+ ; // Expected
+ }
+ } else {
+ checkTypeKind(moduleNoType.getKind(), visitor.visit(moduleNoType));
+ }
+ }
+
+ return true;
+ }
+
+ private NoType getPackageNoType() {
+ TypeMirror type = elements.getPackageElement("java.lang").asType();
+ checkTypeKind(TypeKind.PACKAGE, type.getKind());
+ return (NoType) type;
+ }
+
+ private NoType getModuleNoType() {
+ TypeMirror type = elements.getModuleElement("java.base").asType();
+ checkTypeKind(TypeKind.MODULE, type.getKind());
+ return (NoType) type;
+ }
+
+ private void checkTypeKind(TypeKind expected, TypeKind retreived) {
+ if (retreived != expected)
+ throw new AssertionError("Unexpected type kind " + retreived);
+ }
+
+ List<TypeVisitor<TypeKind, String>> getVisitors() {
+ return List.of(new TypeKindVisitor6<>(null) {
+ @Override
+ protected TypeKind defaultAction(TypeMirror e, String p) {
+ throw new AssertionError("Should not reach");
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsNone(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+ return t.getKind();
+ }
+ // Leave default behavior for a NoType module
+ },
+
+ new TypeKindVisitor7<>(null){
+ @Override
+ protected TypeKind defaultAction(TypeMirror e, String p) {
+ throw new AssertionError("Should not reach");
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsNone(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+ return t.getKind();
+ }
+ // Leave default behavior for a NoType module
+
+ },
+
+ new TypeKindVisitor8<>(null){
+ @Override
+ protected TypeKind defaultAction(TypeMirror e, String p) {
+ throw new AssertionError("Should not reach");
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsNone(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+ return t.getKind();
+ }
+ // Leave default behavior for a NoType module
+
+ },
+
+ new TypeKindVisitor9<>(null){
+ @Override
+ protected TypeKind defaultAction(TypeMirror e, String p) {
+ throw new AssertionError("Should not reach");
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsNone(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+ return t.getKind();
+ }
+
+ @Override
+ public TypeKind visitNoTypeAsModule(NoType t, String p) {
+ return t.getKind();
+ }
+ });
+ }
+}
--- a/test/langtools/tools/jdeps/MultiReleaseJar.java Wed Nov 29 22:35:35 2017 +0100
+++ b/test/langtools/tools/jdeps/MultiReleaseJar.java Wed Nov 29 22:40:23 2017 +0100
@@ -240,17 +240,26 @@
cmds[0] = cmdPath.resolve(cmds[0]).toString();
ProcessBuilder pb = new ProcessBuilder(cmds);
pb.directory(mrjar.toFile());
- Process p = pb.start();
- p.waitFor(10, TimeUnit.SECONDS);
- String out;
- try (InputStream is = p.getInputStream()) {
- out = new String(is.readAllBytes());
+ Process p = null;
+ try {
+ p = pb.start();
+ p.waitFor();
+
+ String out;
+ try (InputStream is = p.getInputStream()) {
+ out = new String(is.readAllBytes());
+ }
+ String err;
+ try (InputStream is = p.getErrorStream()) {
+ err = new String(is.readAllBytes());
+ }
+ return new Result(cmd, p.exitValue(), out, err);
+ } catch (Throwable t) {
+ if (p != null) {
+ p.destroyForcibly().waitFor();
+ }
+ throw t;
}
- String err;
- try (InputStream is = p.getErrorStream()) {
- err = new String(is.readAllBytes());
- }
- return new Result(cmd, p.exitValue(), out, err);
}
void checkResult(Result r) throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/es6/JDK-8059835.js Wed Nov 29 22:40:23 2017 +0100
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8059835: Optimistic splitting doesn't work with let and const
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -Dnashorn.compiler.splitter.threshold=100
+ * @fork
+ */
+
+function f() {
+ let sum = 0;
+ const c = 13;
+ if (true) {
+ let x = 0;
+ const y = 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ sum += x;
+ sum += y;
+ }
+ outer: while (true) {
+ let x = 0;
+ const y = 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ sum += x;
+ sum += y;
+ sum += c;
+ let i = 0;
+ const k = 1;
+ while (true) {
+ x += k;
+ if (++i === 10) {
+ break outer;
+ }
+ }
+ x += k;
+ }
+ return sum;
+}
+
+function g() {
+ let sum = 0;
+ const c = 13;
+ if (true) {
+ let x = 0;
+ const y = 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ sum += x;
+ sum += y;
+ }
+ outer: while (true) {
+ let x = 0;
+ const y = 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ x += 1;
+ sum += x;
+ sum += y;
+ sum += c;
+ let i = 0;
+ const k = 1;
+ while (true) {
+ x += k;
+ if (++i === 10) return 'abc';
+ }
+ x += k;
+ }
+ return sum;
+}
+
+Assert.assertTrue(f() === 80);
+Assert.assertTrue(g() === 'abc');