--- a/.hgtags-top-repo Thu Aug 25 21:18:44 2016 +0000
+++ b/.hgtags-top-repo Wed Jul 05 22:08:15 2017 +0200
@@ -375,3 +375,4 @@
d94d54a3192fea79234c3ac55cd0b4052d45e954 jdk-9+130
8728756c2f70a79a90188f4019cfd6b9a275765c jdk-9+131
a24702d4d5ab0015a5c553ed57f66fce7d85155e jdk-9+132
+be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133
--- a/hotspot/.hgtags Thu Aug 25 21:18:44 2016 +0000
+++ b/hotspot/.hgtags Wed Jul 05 22:08:15 2017 +0200
@@ -535,3 +535,4 @@
7d54c7056328b6a2bf4877458b8f4d8cd870f93b jdk-9+130
943bf73b49c33c2d7cbd796f6a4ae3c7a00ae932 jdk-9+131
713951c08aa26813375175c2ab6cc99ff2a56903 jdk-9+132
+a25e0fb6033245ab075136e744d362ce765464cd jdk-9+133
--- a/hotspot/src/share/vm/gc/g1/g1Analytics.cpp Thu Aug 25 21:18:44 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1Analytics.cpp Wed Jul 05 22:08:15 2017 +0200
@@ -316,14 +316,10 @@
return get_new_size_prediction(_pending_cards_seq);
}
-double G1Analytics::oldest_known_gc_end_time_sec() const {
+double G1Analytics::last_known_gc_end_time_sec() const {
return _recent_prev_end_times_for_all_gcs_sec->oldest();
}
-double G1Analytics::last_known_gc_end_time_sec() const {
- return _recent_prev_end_times_for_all_gcs_sec->last();
-}
-
void G1Analytics::update_recent_gc_times(double end_time_sec,
double pause_time_ms) {
_recent_gc_times_ms->add(pause_time_ms);
--- a/hotspot/src/share/vm/gc/g1/g1Analytics.hpp Thu Aug 25 21:18:44 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1Analytics.hpp Wed Jul 05 22:08:15 2017 +0200
@@ -155,7 +155,6 @@
void update_recent_gc_times(double end_time_sec, double elapsed_ms);
void compute_pause_time_ratio(double interval_ms, double pause_time_ms);
- double oldest_known_gc_end_time_sec() const;
double last_known_gc_end_time_sec() const;
};
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Aug 25 21:18:44 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Wed Jul 05 22:08:15 2017 +0200
@@ -28,7 +28,6 @@
#include "classfile/symbolTable.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
-#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/bufferingOopClosure.hpp"
#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/concurrentG1RefineThread.hpp"
@@ -2474,19 +2473,8 @@
}
jlong G1CollectedHeap::millis_since_last_gc() {
- jlong now = os::elapsed_counter() / NANOSECS_PER_MILLISEC;
- const G1Analytics* analytics = _g1_policy->analytics();
- double last = analytics->last_known_gc_end_time_sec();
- jlong ret_val = now - (last * 1000);
- if (ret_val < 0) {
- // See the notes in GenCollectedHeap::millis_since_last_gc()
- // for more information about the implementation.
- log_warning(gc)("Detected clock going backwards. "
- "Milliseconds since last GC would be " JLONG_FORMAT
- ". returning zero instead.", ret_val);
- return 0;
- }
- return ret_val;
+ // assert(false, "NYI");
+ return 0;
}
void G1CollectedHeap::prepare_for_verify() {
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp Thu Aug 25 21:18:44 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp Wed Jul 05 22:08:15 2017 +0200
@@ -604,7 +604,7 @@
_analytics->report_alloc_rate_ms(alloc_rate_ms);
double interval_ms =
- (end_time_sec - _analytics->oldest_known_gc_end_time_sec()) * 1000.0;
+ (end_time_sec - _analytics->last_known_gc_end_time_sec()) * 1000.0;
_analytics->update_recent_gc_times(end_time_sec, pause_time_ms);
_analytics->compute_pause_time_ratio(interval_ms, pause_time_ms);
}
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Thu Aug 25 21:18:44 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Wed Jul 05 22:08:15 2017 +0200
@@ -1256,21 +1256,21 @@
};
jlong GenCollectedHeap::millis_since_last_gc() {
- // javaTimeNanos() is guaranteed to be monotonically non-decreasing
- // provided the underlying platform provides such a time source
- // (and it is bug free). So we still have to guard against getting
- // back a time later than 'now'.
+ // We need a monotonically non-decreasing time in ms but
+ // os::javaTimeMillis() does not guarantee monotonicity.
jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
GenTimeOfLastGCClosure tolgc_cl(now);
// iterate over generations getting the oldest
// time that a generation was collected
generation_iterate(&tolgc_cl, false);
+ // javaTimeNanos() is guaranteed to be monotonically non-decreasing
+ // provided the underlying platform provides such a time source
+ // (and it is bug free). So we still have to guard against getting
+ // back a time later than 'now'.
jlong retVal = now - tolgc_cl.time();
if (retVal < 0) {
- log_warning(gc)("Detected clock going backwards. "
- "Milliseconds since last GC would be " JLONG_FORMAT
- ". returning zero instead.", retVal);
+ NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);)
return 0;
}
return retVal;
--- a/jdk/.hgtags Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/.hgtags Wed Jul 05 22:08:15 2017 +0200
@@ -375,3 +375,4 @@
6c827500e34587061af97ad6fef0e859280255c5 jdk-9+130
8c57f4c293bbc5609928308a6d91ba765760b5f9 jdk-9+131
d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132
+3cdae27c90b5e41afe75eab904fda19fac076330 jdk-9+133
--- a/jdk/make/data/cryptopolicy/limited/default_local.policy Thu Aug 25 21:18:44 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-// Some countries have import limits on crypto strength. This policy file
-// is worldwide importable.
-
-grant {
- permission javax.crypto.CryptoPermission "DES", 64;
- permission javax.crypto.CryptoPermission "DESede", *;
- permission javax.crypto.CryptoPermission "RC2", 128,
- "javax.crypto.spec.RC2ParameterSpec", 128;
- permission javax.crypto.CryptoPermission "RC4", 128;
- permission javax.crypto.CryptoPermission "RC5", 128,
- "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
- permission javax.crypto.CryptoPermission "RSA", *;
- permission javax.crypto.CryptoPermission *, 128;
-};
--- a/jdk/make/data/cryptopolicy/limited/exempt_local.policy Thu Aug 25 21:18:44 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-// Some countries have import limits on crypto strength. So this file
-// will be useful.
-
-grant {
- // There is no restriction to any algorithms if KeyRecovery is enforced.
- permission javax.crypto.CryptoPermission *, "KeyRecovery";
-
- // There is no restriction to any algorithms if KeyEscrow is enforced.
- permission javax.crypto.CryptoPermission *, "KeyEscrow";
-
- // There is no restriction to any algorithms if KeyWeakening is enforced.
- permission javax.crypto.CryptoPermission *, "KeyWeakening";
-};
--- a/jdk/make/data/cryptopolicy/unlimited/default_US_export.policy Thu Aug 25 21:18:44 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// Manufacturing policy file.
-grant {
- // There is no restriction to any algorithms.
- permission javax.crypto.CryptoAllPermission;
-};
--- a/jdk/make/data/cryptopolicy/unlimited/default_local.policy Thu Aug 25 21:18:44 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// Country-specific policy file for countries with no limits on crypto strength.
-grant {
- // There is no restriction to any algorithms.
- permission javax.crypto.CryptoAllPermission;
-};
--- a/jdk/make/gendata/Gendata-java.base.gmk Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/make/gendata/Gendata-java.base.gmk Wed Jul 05 22:08:15 2017 +0200
@@ -34,7 +34,7 @@
include GendataBlacklistedCerts.gmk
-include GendataPolicyJars.gmk
+include GendataCryptoPolicy.gmk
################################################################################
@@ -64,13 +64,19 @@
GENDATA_JAVA_SECURITY_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/java.security
GENDATA_JAVA_SECURITY := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/java.security
+ifeq ($(UNLIMITED_CRYPTO), true)
+ CRYPTO.POLICY := unlimited
+else
+ CRYPTO.POLICY := limited
+endif
+
# RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile
$(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC)
$(call LogInfo, Generating java.security)
$(call MakeDir, $(@D))
$(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \
- $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC)
+ $(OPENJDK_TARGET_CPU_ARCH) $(CRYPTO.POLICY) $(RESTRICTED_PKGS_SRC)
TARGETS += $(GENDATA_JAVA_SECURITY)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/gendata/GendataCryptoPolicy.gmk Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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.
+#
+
+#
+# In pre-JDK9 releases, Oracle JDK has had a separately downloadable set
+# of policy files which has been a nightmare for deployment.
+#
+# We now create 2 complete initial sets of policy files and package into
+# 2 different directories. The crypto.policy Security property will select
+# the active policy.
+#
+# It will be up to the user/deployer to make an informed choice
+# as to whether they are legally entitled to use the unlimited policy
+# file in their environment. The $(UNLIMITED_CRYPTO) make variable
+# determines the default directory/policy.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+
+################################################################################
+POLICY_DIR := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/policy
+LIMITED_POLICY_DIR := $(POLICY_DIR)/limited
+UNLIMITED_POLICY_DIR := $(POLICY_DIR)/unlimited
+
+POLICY_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/conf/security/policy
+LIMITED_POLICY_SRC_DIR := $(POLICY_SRC_DIR)/limited
+UNLIMITED_POLICY_SRC_DIR := $(POLICY_SRC_DIR)/unlimited
+
+$(POLICY_DIR)/README.txt: $(POLICY_SRC_DIR)/README.txt
+ $(install-file)
+
+$(LIMITED_POLICY_DIR)/%: $(LIMITED_POLICY_SRC_DIR)/%
+ $(install-file)
+
+$(UNLIMITED_POLICY_DIR)/%: $(UNLIMITED_POLICY_SRC_DIR)/%
+ $(install-file)
+
+TARGETS += \
+ $(POLICY_DIR)/README.txt \
+ $(LIMITED_POLICY_DIR)/default_US_export.policy \
+ $(LIMITED_POLICY_DIR)/default_local.policy \
+ $(LIMITED_POLICY_DIR)/exempt_local.policy \
+ $(UNLIMITED_POLICY_DIR)/default_US_export.policy \
+ $(UNLIMITED_POLICY_DIR)/default_local.policy \
+
+################################################################################
--- a/jdk/make/gendata/GendataPolicyJars.gmk Thu Aug 25 21:18:44 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-#
-# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# 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
-include JarArchive.gmk
-
-
-################################################################################
-
-US_EXPORT_POLICY_JAR_DST := \
- $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/US_export_policy.jar
-
-US_EXPORT_POLICY_JAR_LIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/limited/US_export_policy.jar
-US_EXPORT_POLICY_JAR_UNLIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy.jar
-
-#
-# TODO fix so that SetupJarArchive does not write files into SRCS
-# then we don't need this extra copying
-#
-# NOTE: We currently do not place restrictions on our limited export
-# policy. This was not a typo. This means we are shipping the same file
-# for both limited and unlimited US_export_policy.jar. Only the local
-# policy file currently has restrictions.
-#
-US_EXPORT_POLICY_JAR_SRC_DIR := \
- $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited
-US_EXPORT_POLICY_JAR_TMP := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/US_export_policy_jar.tmp
-
-$(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/%
- $(install-file)
-
-US_EXPORT_POLICY_JAR_DEPS := \
- $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy
-
-$(eval $(call SetupJarArchive, BUILD_US_EXPORT_POLICY_JAR, \
- DEPENDENCIES := $(US_EXPORT_POLICY_JAR_DEPS), \
- SRCS := $(US_EXPORT_POLICY_JAR_TMP), \
- SUFFIXES := .policy, \
- JAR := $(US_EXPORT_POLICY_JAR_UNLIMITED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true, \
-))
-
-$(US_EXPORT_POLICY_JAR_LIMITED): \
- $(US_EXPORT_POLICY_JAR_UNLIMITED)
- $(call LogInfo, Copying unlimited $(patsubst $(OUTPUT_ROOT)/%,%,$@))
- $(install-file)
-
-TARGETS += $(US_EXPORT_POLICY_JAR_LIMITED) $(US_EXPORT_POLICY_JAR_UNLIMITED)
-
-ifeq ($(UNLIMITED_CRYPTO), true)
- $(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_UNLIMITED)
- $(install-file)
-else
- $(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_LIMITED)
- $(install-file)
-endif
-
-POLICY_JARS += $(US_EXPORT_POLICY_JAR_DST)
-
-################################################################################
-
-LOCAL_POLICY_JAR_DST := \
- $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/local_policy.jar
-
-LOCAL_POLICY_JAR_LIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy.jar
-LOCAL_POLICY_JAR_UNLIMITED := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy.jar
-
-#
-# TODO fix so that SetupJarArchive does not write files into SRCS
-# then we don't need this extra copying
-#
-LOCAL_POLICY_JAR_LIMITED_TMP := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/limited/local_policy_jar.tmp
-LOCAL_POLICY_JAR_UNLIMITED_TMP := \
- $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy_jar.tmp
-
-$(LOCAL_POLICY_JAR_LIMITED_TMP)/%: \
- $(JDK_TOPDIR)/make/data/cryptopolicy/limited/%
- $(install-file)
-
-$(LOCAL_POLICY_JAR_UNLIMITED_TMP)/%: \
- $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited/%
- $(install-file)
-
-$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_LIMITED, \
- DEPENDENCIES := $(LOCAL_POLICY_JAR_LIMITED_TMP)/exempt_local.policy \
- $(LOCAL_POLICY_JAR_LIMITED_TMP)/default_local.policy, \
- SRCS := $(LOCAL_POLICY_JAR_LIMITED_TMP), \
- SUFFIXES := .policy, \
- JAR := $(LOCAL_POLICY_JAR_LIMITED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: limited, \
- SKIP_METAINF := true, \
-))
-
-$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_UNLIMITED, \
- DEPENDENCIES := $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/default_local.policy, \
- SRCS := $(LOCAL_POLICY_JAR_UNLIMITED_TMP), \
- SUFFIXES := .policy, \
- JAR := $(LOCAL_POLICY_JAR_UNLIMITED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true, \
-))
-
-TARGETS += $(LOCAL_POLICY_JAR_LIMITED) $(LOCAL_POLICY_JAR_UNLIMITED)
-
-ifeq ($(UNLIMITED_CRYPTO), true)
- $(LOCAL_POLICY_JAR_DST): $(LOCAL_POLICY_JAR_UNLIMITED)
- $(install-file)
-else
- $(LOCAL_POLICY_JAR_DST): $(LOCAL_POLICY_JAR_LIMITED)
- $(install-file)
-endif
-
-POLICY_JARS += $(LOCAL_POLICY_JAR_DST)
-TARGETS += $(POLICY_JARS)
-
-################################################################################
-
-$(eval $(call IncludeCustomExtension, jdk, gendata/GendataPolicyJars.gmk))
--- a/jdk/make/launcher/Launcher-jdk.jdeps.gmk Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/make/launcher/Launcher-jdk.jdeps.gmk Wed Jul 05 22:08:15 2017 +0200
@@ -36,3 +36,9 @@
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
))
+
+$(eval $(call SetupBuildLauncher, jdeprscan, \
+ MAIN_CLASS := com.sun.tools.jdeprscan.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
--- a/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,6 @@
CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \
$(LIBJAVA_HEADER_FLAGS) \
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.crypto.pkcs11, \
- DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE, \
- DISABLED_WARNINGS_microsoft := 4013 4267, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libj2pkcs11/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,8 @@
*
* 1. Adds additional packages to the package.access and
* package.definition security properties.
- * 2. Filter out platform-unrelated parts
+ * 2. Filter out platform-unrelated parts.
+ * 3. Set the JCE jurisdiction policy directory.
*
* In order to easily maintain platform-related entries, every item
* (including the last line) in package.access and package.definition
@@ -50,12 +51,13 @@
public static void main(String[] args) throws Exception {
- if (args.length < 4) {
+ if (args.length < 5) {
System.err.println("Usage: java MakeJavaSecurity " +
"[input java.security file name] " +
"[output java.security file name] " +
"[openjdk target os] " +
"[openjdk target cpu architecture]" +
+ "[JCE jurisdiction policy directory]" +
"[more restricted packages file name?]");
System.exit(1);
@@ -63,8 +65,8 @@
// more restricted packages
List<String> extraLines;
- if (args.length == 5) {
- extraLines = Files.readAllLines(Paths.get(args[4]));
+ if (args.length == 6) {
+ extraLines = Files.readAllLines(Paths.get(args[5]));
} else {
extraLines = Collections.emptyList();
}
@@ -135,6 +137,16 @@
}
}
+ // Set the JCE policy value
+ for (int i = 0; i < lines.size(); i++) {
+ String line = lines.get(i);
+ int index = line.indexOf("crypto.policydir-tbd");
+ if (index >= 0) {
+ String prefix = line.substring(0, index);
+ lines.set(i, prefix + args[4]);
+ }
+ }
+
// Clean up the last line of PKG_ACC and PKG_DEF blocks.
// Not really necessary since a blank line follows.
boolean inBlock = false;
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java Wed Jul 05 22:08:15 2017 +0200
@@ -986,8 +986,9 @@
if (padding != null) {
int padStart = padding.unpad(outWithPadding, 0, outLen);
if (padStart < 0) {
- throw new BadPaddingException("Given final block not "
- + "properly padded");
+ throw new BadPaddingException("Given final block not " +
+ "properly padded. Such issues can arise if a bad key " +
+ "is used during decryption.");
}
outLen = padStart;
}
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Wed Jul 05 22:08:15 2017 +0200
@@ -331,12 +331,6 @@
* Note that this method does not check whether the requested class
* is accessible to its caller.
*
- * <p> If the {@code loader} is {@code null}, and a security
- * manager is present, and the caller's class loader is not null, then this
- * method calls the security manager's {@code checkPermission} method
- * with a {@code RuntimePermission("getClassLoader")} permission to
- * ensure it's ok to access the bootstrap class loader.
- *
* @param name fully qualified name of the desired class
* @param initialize if {@code true} the class will be initialized.
* See Section 12.4 of <em>The Java Language Specification</em>.
@@ -348,6 +342,11 @@
* by this method fails
* @exception ClassNotFoundException if the class cannot be located by
* the specified class loader
+ * @exception SecurityException
+ * if a security manager is present, and the {@code loader} is
+ * {@code null}, and the caller's class loader is not
+ * {@code null}, and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @see java.lang.Class#forName(String)
* @see java.lang.ClassLoader
@@ -782,22 +781,17 @@
* null in such implementations if this class was loaded by the bootstrap
* class loader.
*
- * <p> If a security manager is present, and the caller's class loader is
- * not null and the caller's class loader is not the same as or an ancestor of
- * the class loader for the class whose class loader is requested, then
- * this method calls the security manager's {@code checkPermission}
- * method with a {@code RuntimePermission("getClassLoader")}
- * permission to ensure it's ok to access the class loader for the class.
- *
* <p>If this object
* represents a primitive type or void, null is returned.
*
* @return the class loader that loaded the class or interface
* represented by this object.
- * @throws SecurityException
- * if a security manager exists and its
- * {@code checkPermission} method denies
- * access to the class loader for the class.
+ * @throws SecurityException
+ * if a security manager is present, and the caller's class loader
+ * is not {@code null} and is not the same as or an ancestor of the
+ * class loader for the class whose class loader is requested,
+ * and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
* @see java.lang.ClassLoader
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Wed Jul 05 22:08:15 2017 +0200
@@ -1537,22 +1537,13 @@
* will return <tt>null</tt> in such implementations if this class loader's
* parent is the bootstrap class loader.
*
- * <p> If a security manager is present, and the invoker's class loader is
- * not <tt>null</tt> and is not an ancestor of this class loader, then this
- * method invokes the security manager's {@link
- * SecurityManager#checkPermission(java.security.Permission)
- * <tt>checkPermission</tt>} method with a {@link
- * RuntimePermission#RuntimePermission(String)
- * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
- * access to the parent class loader is permitted. If not, a
- * <tt>SecurityException</tt> will be thrown. </p>
- *
* @return The parent <tt>ClassLoader</tt>
*
* @throws SecurityException
- * If a security manager exists and its <tt>checkPermission</tt>
- * method doesn't allow access to this class loader's parent class
- * loader.
+ * If a security manager is present, and the caller's class loader
+ * is not {@code null} and is not an ancestor of this class loader,
+ * and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @since 1.2
*/
@@ -1590,12 +1581,11 @@
* @return The platform {@code ClassLoader}.
*
* @throws SecurityException
- * If a security manager exists and the caller's class loader is
- * not {@code null} and the caller's class loader is not the same
+ * If a security manager is present, and the caller's class loader is
+ * not {@code null}, and the caller's class loader is not the same
* as or an ancestor of the platform class loader,
- * and the {@link SecurityManager#checkPermission(java.security.Permission)
- * checkPermission} method denies {@code RuntimePermission("getClassLoader")}
- * to access the platform class loader.
+ * and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @since 9
*/
@@ -1636,17 +1626,6 @@
* If circular initialization of the system class loader is detected then
* an unspecified error or exception is thrown.
*
- * <p> If a security manager is present, and the invoker's class loader is
- * not <tt>null</tt> and the invoker's class loader is not the same as or
- * an ancestor of the system class loader, then this method invokes the
- * security manager's {@link
- * SecurityManager#checkPermission(java.security.Permission)
- * <tt>checkPermission</tt>} method with a {@link
- * RuntimePermission#RuntimePermission(String)
- * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
- * access to the system class loader. If not, a
- * <tt>SecurityException</tt> will be thrown. </p>
- *
* @implNote The system property to override the system class loader is not
* examined until the VM is almost fully initialized. Code that executes
* this method during startup should take care not to cache the return
@@ -1656,8 +1635,10 @@
* <tt>null</tt> if none
*
* @throws SecurityException
- * If a security manager exists and its <tt>checkPermission</tt>
- * method doesn't allow access to the system class loader.
+ * If a security manager is present, and the caller's class loader
+ * is not {@code null} and is not the same as or an ancestor of the
+ * system class loader, and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
--- a/jdk/src/java.base/share/classes/java/lang/Math.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java Wed Jul 05 22:08:15 2017 +0200
@@ -1370,8 +1370,13 @@
* result is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
- * In other words, the result is the same as the value of the expression:
- * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code float} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value:<br>
+ * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
@@ -1389,8 +1394,13 @@
* is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
- * In other words, the result is the same as the value of the expression:
- * <p>{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code double} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value:<br>
+ * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java Wed Jul 05 22:08:15 2017 +0200
@@ -1070,8 +1070,13 @@
* result is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
- * In other words, the result is the same as the value of the expression:
- * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code float} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value: <br>
+ * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
@@ -1089,8 +1094,13 @@
* is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
- * In other words, the result is the same as the value of the expression:
- * <p>{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code double} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value: <br>
+ * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java Wed Jul 05 22:08:15 2017 +0200
@@ -1507,28 +1507,25 @@
}
/**
- * Returns the context ClassLoader for this Thread. The context
- * ClassLoader is provided by the creator of the thread for use
+ * Returns the context {@code ClassLoader} for this thread. The context
+ * {@code ClassLoader} is provided by the creator of the thread for use
* by code running in this thread when loading classes and resources.
* If not {@linkplain #setContextClassLoader set}, the default is the
- * ClassLoader context of the parent Thread. The context ClassLoader of the
+ * {@code ClassLoader} context of the parent thread. The context
+ * {@code ClassLoader} of the
* primordial thread is typically set to the class loader used to load the
* application.
*
- * <p>If a security manager is present, and the invoker's class loader is not
- * {@code null} and is not the same as or an ancestor of the context class
- * loader, then this method invokes the security manager's {@link
- * SecurityManager#checkPermission(java.security.Permission) checkPermission}
- * method with a {@link RuntimePermission RuntimePermission}{@code
- * ("getClassLoader")} permission to verify that retrieval of the context
- * class loader is permitted.
*
- * @return the context ClassLoader for this Thread, or {@code null}
+ * @return the context {@code ClassLoader} for this thread, or {@code null}
* indicating the system class loader (or, failing that, the
* bootstrap class loader)
*
* @throws SecurityException
- * if the current thread cannot get the context ClassLoader
+ * if a security manager is present, and the caller's class loader
+ * is not {@code null} and is not the same as or an ancestor of the
+ * context class loader, and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @since 1.2
*/
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Jul 05 22:08:15 2017 +0200
@@ -497,6 +497,10 @@
String shortTypes = LambdaForm.shortenSignature(types);
String className = SPECIES_CLASS_PREFIX + shortTypes;
Class<?> c = BootLoader.loadClassOrNull(className);
+ if (TRACE_RESOLVE) {
+ System.out.println("[BMH_RESOLVE] " + shortTypes +
+ (c != null ? " (success)" : " (fail)") );
+ }
if (c != null) {
return c.asSubclass(BoundMethodHandle.class);
} else {
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Wed Jul 05 22:08:15 2017 +0200
@@ -492,7 +492,7 @@
}
// Caching machinery for field accessors:
- private static final byte
+ static final byte
AF_GETFIELD = 0,
AF_PUTFIELD = 1,
AF_GETSTATIC = 2,
@@ -502,7 +502,7 @@
AF_LIMIT = 6;
// Enumerate the different field kinds using Wrapper,
// with an extra case added for checked references.
- private static final int
+ static final int
FT_LAST_WRAPPER = Wrapper.COUNT-1,
FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
FT_CHECKED_REF = FT_LAST_WRAPPER+1,
@@ -515,7 +515,7 @@
@Stable
private static final LambdaForm[] ACCESSOR_FORMS
= new LambdaForm[afIndex(AF_LIMIT, false, 0)];
- private static int ftypeKind(Class<?> ftype) {
+ static int ftypeKind(Class<?> ftype) {
if (ftype.isPrimitive())
return Wrapper.forPrimitiveType(ftype).ordinal();
else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
@@ -566,7 +566,64 @@
private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
- private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
+ private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
+ if (isGetter) {
+ if (isVolatile) {
+ switch (wrapper) {
+ case BOOLEAN: return GET_BOOLEAN_VOLATILE;
+ case BYTE: return GET_BYTE_VOLATILE;
+ case SHORT: return GET_SHORT_VOLATILE;
+ case CHAR: return GET_CHAR_VOLATILE;
+ case INT: return GET_INT_VOLATILE;
+ case LONG: return GET_LONG_VOLATILE;
+ case FLOAT: return GET_FLOAT_VOLATILE;
+ case DOUBLE: return GET_DOUBLE_VOLATILE;
+ case OBJECT: return GET_OBJECT_VOLATILE;
+ }
+ } else {
+ switch (wrapper) {
+ case BOOLEAN: return GET_BOOLEAN;
+ case BYTE: return GET_BYTE;
+ case SHORT: return GET_SHORT;
+ case CHAR: return GET_CHAR;
+ case INT: return GET_INT;
+ case LONG: return GET_LONG;
+ case FLOAT: return GET_FLOAT;
+ case DOUBLE: return GET_DOUBLE;
+ case OBJECT: return GET_OBJECT;
+ }
+ }
+ } else {
+ if (isVolatile) {
+ switch (wrapper) {
+ case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
+ case BYTE: return PUT_BYTE_VOLATILE;
+ case SHORT: return PUT_SHORT_VOLATILE;
+ case CHAR: return PUT_CHAR_VOLATILE;
+ case INT: return PUT_INT_VOLATILE;
+ case LONG: return PUT_LONG_VOLATILE;
+ case FLOAT: return PUT_FLOAT_VOLATILE;
+ case DOUBLE: return PUT_DOUBLE_VOLATILE;
+ case OBJECT: return PUT_OBJECT_VOLATILE;
+ }
+ } else {
+ switch (wrapper) {
+ case BOOLEAN: return PUT_BOOLEAN;
+ case BYTE: return PUT_BYTE;
+ case SHORT: return PUT_SHORT;
+ case CHAR: return PUT_CHAR;
+ case INT: return PUT_INT;
+ case LONG: return PUT_LONG;
+ case FLOAT: return PUT_FLOAT;
+ case DOUBLE: return PUT_DOUBLE;
+ case OBJECT: return PUT_OBJECT;
+ }
+ }
+ }
+ throw new AssertionError("Invalid arguments");
+ }
+
+ static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
boolean isStatic = (formOp >= AF_GETSTATIC);
boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
@@ -576,24 +633,14 @@
assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
// getObject, putIntVolatile, etc.
- StringBuilder nameBuilder = new StringBuilder();
- if (isGetter) {
- nameBuilder.append("get");
- } else {
- nameBuilder.append("put");
- }
- nameBuilder.append(fw.primitiveSimpleName());
- nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
- if (isVolatile) {
- nameBuilder.append("Volatile");
- }
+ Kind kind = getFieldKind(isGetter, isVolatile, fw);
MethodType linkerType;
if (isGetter)
linkerType = MethodType.methodType(ft, Object.class, long.class);
else
linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
- MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
+ MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
} catch (ReflectiveOperationException ex) {
@@ -620,6 +667,7 @@
final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
final int F_OFFSET = nameCursor++; // Either static offset or field offset.
final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
+ final int U_HOLDER = nameCursor++; // UNSAFE holder
final int INIT_BAR = (needsInit ? nameCursor++ : -1);
final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
final int LINKER_CALL = nameCursor++;
@@ -632,7 +680,7 @@
names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
Object[] outArgs = new Object[1 + linkerType.parameterCount()];
assert(outArgs.length == (isGetter ? 3 : 4));
- outArgs[0] = UNSAFE;
+ outArgs[0] = names[U_HOLDER] = new Name(NF_UNSAFE);
if (isStatic) {
outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]);
outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]);
@@ -650,6 +698,7 @@
for (Name n : names) assert(n != null);
// add some detail to the lambdaForm debugname,
// significant only for debugging
+ StringBuilder nameBuilder = new StringBuilder(kind.methodName);
if (isStatic) {
nameBuilder.append("Static");
} else {
@@ -657,7 +706,12 @@
}
if (needsCast) nameBuilder.append("Cast");
if (needsInit) nameBuilder.append("Init");
- return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
+ if (needsCast || needsInit) {
+ // can't use the pre-generated form when casting and/or initializing
+ return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
+ } else {
+ return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind);
+ }
}
/**
@@ -674,7 +728,8 @@
NF_staticOffset,
NF_checkCast,
NF_allocateInstance,
- NF_constructorMethod;
+ NF_constructorMethod,
+ NF_UNSAFE;
static {
try {
NamedFunction nfs[] = {
@@ -697,7 +752,9 @@
NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("allocateInstance", Object.class)),
NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
- .getDeclaredMethod("constructorMethod", Object.class))
+ .getDeclaredMethod("constructorMethod", Object.class)),
+ NF_UNSAFE = new NamedFunction(new MemberName(MethodHandleStatics.class
+ .getDeclaredField("UNSAFE")))
};
// Each nf must be statically invocable or we get tied up in our bootstraps.
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java Wed Jul 05 22:08:15 2017 +0200
@@ -28,9 +28,11 @@
import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.HashSet;
+import sun.invoke.util.Wrapper;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
/**
* Helper class to assist the GenerateJLIClassesPlugin to get access to
@@ -66,14 +68,38 @@
static byte[] generateDirectMethodHandleHolderClassBytes(String className,
MethodType[] methodTypes, int[] types) {
- LambdaForm[] forms = new LambdaForm[methodTypes.length];
- String[] names = new String[methodTypes.length];
- for (int i = 0; i < forms.length; i++) {
- forms[i] = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i],
- types[i]);
- names[i] = forms[i].kind.defaultLambdaName;
+ ArrayList<LambdaForm> forms = new ArrayList<>();
+ ArrayList<String> names = new ArrayList<>();
+ for (int i = 0; i < methodTypes.length; i++) {
+ LambdaForm form = DirectMethodHandle
+ .makePreparedLambdaForm(methodTypes[i], types[i]);
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
}
- return generateCodeBytesForLFs(className, names, forms);
+ for (Wrapper wrapper : Wrapper.values()) {
+ if (wrapper == Wrapper.VOID) {
+ continue;
+ }
+ for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
+ int ftype = DirectMethodHandle.ftypeKind(wrapper.primitiveType());
+ LambdaForm form = DirectMethodHandle
+ .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
+ if (form.kind != LambdaForm.Kind.GENERIC) {
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
+ }
+ // volatile
+ form = DirectMethodHandle
+ .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
+ if (form.kind != LambdaForm.Kind.GENERIC) {
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
+ }
+ }
+ }
+ return generateCodeBytesForLFs(className,
+ names.toArray(new String[0]),
+ forms.toArray(new LambdaForm[0]));
}
static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
@@ -107,6 +133,34 @@
forms.toArray(new LambdaForm[0]));
}
+ static byte[] generateInvokersHolderClassBytes(String className,
+ MethodType[] methodTypes) {
+
+ HashSet<MethodType> dedupSet = new HashSet<>();
+ ArrayList<LambdaForm> forms = new ArrayList<>();
+ ArrayList<String> names = new ArrayList<>();
+ int[] types = {
+ MethodTypeForm.LF_EX_LINKER,
+ MethodTypeForm.LF_EX_INVOKER,
+ MethodTypeForm.LF_GEN_LINKER,
+ MethodTypeForm.LF_GEN_INVOKER
+ };
+ for (int i = 0; i < methodTypes.length; i++) {
+ // generate methods representing invokers of the specified type
+ if (dedupSet.add(methodTypes[i])) {
+ for (int type : types) {
+ LambdaForm invokerForm = Invokers.invokeHandleForm(methodTypes[i],
+ /*customized*/false, type);
+ forms.add(invokerForm);
+ names.add(invokerForm.kind.defaultLambdaName);
+ }
+ }
+ }
+ return generateCodeBytesForLFs(className,
+ names.toArray(new String[0]),
+ forms.toArray(new LambdaForm[0]));
+ }
+
/*
* Generate customized code for a set of LambdaForms of specified types into
* a class with a specified name.
@@ -166,4 +220,5 @@
BoundMethodHandle.Factory.generateConcreteBMHClassBytes(
shortTypes, types, className));
}
+
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 22:08:15 2017 +0200
@@ -607,7 +607,10 @@
private static MemberName resolveFrom(String name, MethodType type, Class<?> holder) {
MemberName member = new MemberName(holder, name, type, REF_invokeStatic);
MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder);
-
+ if (TRACE_RESOLVE) {
+ System.out.println("[LF_RESOLVE] " + holder.getName() + " " + name + " " +
+ shortenSignature(basicTypeSignature(type)) + (resolvedMember != null ? " (success)" : " (fail)") );
+ }
return resolvedMember;
}
@@ -629,6 +632,28 @@
name = name + "_" + form.returnType().basicTypeChar();
return resolveFrom(name, invokerType, LambdaForm.Holder.class);
}
+ case EXACT_INVOKER: // fall-through
+ case EXACT_LINKER: // fall-through
+ case GENERIC_INVOKER: // fall-through
+ case GENERIC_LINKER: return resolveFrom(name, invokerType.basicType(), Invokers.Holder.class);
+ case GET_OBJECT: // fall-through
+ case GET_BOOLEAN: // fall-through
+ case GET_BYTE: // fall-through
+ case GET_CHAR: // fall-through
+ case GET_SHORT: // fall-through
+ case GET_INT: // fall-through
+ case GET_LONG: // fall-through
+ case GET_FLOAT: // fall-through
+ case GET_DOUBLE: // fall-through
+ case PUT_OBJECT: // fall-through
+ case PUT_BOOLEAN: // fall-through
+ case PUT_BYTE: // fall-through
+ case PUT_CHAR: // fall-through
+ case PUT_SHORT: // fall-through
+ case PUT_INT: // fall-through
+ case PUT_LONG: // fall-through
+ case PUT_FLOAT: // fall-through
+ case PUT_DOUBLE: // fall-through
case DIRECT_INVOKE_INTERFACE: // fall-through
case DIRECT_INVOKE_SPECIAL: // fall-through
case DIRECT_INVOKE_STATIC: // fall-through
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java Wed Jul 05 22:08:15 2017 +0200
@@ -36,6 +36,7 @@
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
/**
* Construction and caching of often-used invokers.
@@ -254,7 +255,7 @@
* @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker");
* 0x02 whether it is for invokeExact or generic invoke
*/
- private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
+ static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
boolean isCached;
if (!customized) {
mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
@@ -263,12 +264,12 @@
isCached = false; // maybe cache if mtype == mtype.basicType()
}
boolean isLinker, isGeneric;
- String debugName;
+ Kind kind;
switch (which) {
- case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; debugName = "invokeExact_MT"; break;
- case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
- case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break;
- case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break;
+ case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; kind = EXACT_LINKER; break;
+ case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; kind = EXACT_INVOKER; break;
+ case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; kind = GENERIC_LINKER; break;
+ case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; kind = GENERIC_INVOKER; break;
default: throw new InternalError();
}
LambdaForm lform;
@@ -323,7 +324,11 @@
names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
}
names[LINKER_CALL] = new Name(outCallType, outArgs);
- lform = new LambdaForm(debugName, INARG_LIMIT, names);
+ if (customized) {
+ lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names);
+ } else {
+ lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names, kind);
+ }
if (isLinker)
lform.compileToBytecode(); // JVM needs a real methodOop
if (isCached)
@@ -614,4 +619,15 @@
}
}
}
+
+ static {
+ // The Holder class will contain pre-generated Invokers resolved
+ // speculatively using MemberName.getFactory().resolveOrNull. However, that
+ // doesn't initialize the class, which subtly breaks inlining etc. By forcing
+ // initialization of the Holder class we avoid these issues.
+ UNSAFE.ensureClassInitialized(Holder.class);
+ }
+
+ /* Placeholder class for Invokers generated ahead of time */
+ final class Holder {}
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Wed Jul 05 22:08:15 2017 +0200
@@ -275,12 +275,52 @@
BOUND_REINVOKER("BMH.reinvoke"),
REINVOKER("MH.reinvoke"),
DELEGATE("MH.delegate"),
+ EXACT_LINKER("MH.invokeExact_MT"),
+ EXACT_INVOKER("MH.exactInvoker"),
+ GENERIC_LINKER("MH.invoke_MT"),
+ GENERIC_INVOKER("MH.invoker"),
DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"),
DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"),
DIRECT_INVOKE_STATIC("DMH.invokeStatic"),
DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"),
DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"),
- DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit");
+ DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit"),
+ GET_OBJECT("getObject"),
+ PUT_OBJECT("putObject"),
+ GET_OBJECT_VOLATILE("getObjectVolatile"),
+ PUT_OBJECT_VOLATILE("putObjectVolatile"),
+ GET_INT("getInt"),
+ PUT_INT("putInt"),
+ GET_INT_VOLATILE("getIntVolatile"),
+ PUT_INT_VOLATILE("putIntVolatile"),
+ GET_BOOLEAN("getBoolean"),
+ PUT_BOOLEAN("putBoolean"),
+ GET_BOOLEAN_VOLATILE("getBooleanVolatile"),
+ PUT_BOOLEAN_VOLATILE("putBooleanVolatile"),
+ GET_BYTE("getByte"),
+ PUT_BYTE("putByte"),
+ GET_BYTE_VOLATILE("getByteVolatile"),
+ PUT_BYTE_VOLATILE("putByteVolatile"),
+ GET_CHAR("getChar"),
+ PUT_CHAR("putChar"),
+ GET_CHAR_VOLATILE("getCharVolatile"),
+ PUT_CHAR_VOLATILE("putCharVolatile"),
+ GET_SHORT("getShort"),
+ PUT_SHORT("putShort"),
+ GET_SHORT_VOLATILE("getShortVolatile"),
+ PUT_SHORT_VOLATILE("putShortVolatile"),
+ GET_LONG("getLong"),
+ PUT_LONG("putLong"),
+ GET_LONG_VOLATILE("getLongVolatile"),
+ PUT_LONG_VOLATILE("putLongVolatile"),
+ GET_FLOAT("getFloat"),
+ PUT_FLOAT("putFloat"),
+ GET_FLOAT_VOLATILE("getFloatVolatile"),
+ PUT_FLOAT_VOLATILE("putFloatVolatile"),
+ GET_DOUBLE("getDouble"),
+ PUT_DOUBLE("putDouble"),
+ GET_DOUBLE_VOLATILE("getDoubleVolatile"),
+ PUT_DOUBLE_VOLATILE("putDoubleVolatile");
final String defaultLambdaName;
final String methodName;
@@ -330,6 +370,10 @@
this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
}
LambdaForm(String debugName,
+ int arity, Name[] names, Kind kind) {
+ this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, kind);
+ }
+ LambdaForm(String debugName,
int arity, Name[] names, boolean forceInline) {
this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
}
@@ -817,54 +861,6 @@
}
}
- private static void computeInitialPreparedForms() {
- // Find all predefined invokers and associate them with canonical empty lambda forms.
- for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
- if (!m.isStatic() || !m.isPackage()) continue;
- MethodType mt = m.getMethodType();
- if (mt.parameterCount() > 0 &&
- mt.parameterType(0) == MethodHandle.class &&
- m.getName().startsWith("interpret_")) {
- String sig = null;
- assert((sig = basicTypeSignature(mt)) != null &&
- m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
- LambdaForm form = new LambdaForm(mt);
- form.vmentry = m;
- form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
- }
- }
- }
-
- // Set this false to disable use of the interpret_L methods defined in this file.
- private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
-
- // The following are predefined exact invokers. The system must build
- // a separate invoker for each distinct signature.
- static Object interpret_L(MethodHandle mh) throws Throwable {
- Object[] av = {mh};
- String sig = null;
- assert(argumentTypesMatch(sig = "L_L", av));
- Object res = mh.form.interpretWithArguments(av);
- assert(returnTypesMatch(sig, av, res));
- return res;
- }
- static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
- Object[] av = {mh, x1};
- String sig = null;
- assert(argumentTypesMatch(sig = "LL_L", av));
- Object res = mh.form.interpretWithArguments(av);
- assert(returnTypesMatch(sig, av, res));
- return res;
- }
- static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
- Object[] av = {mh, x1, x2};
- String sig = null;
- assert(argumentTypesMatch(sig = "LLL_L", av));
- Object res = mh.form.interpretWithArguments(av);
- assert(returnTypesMatch(sig, av, res));
- return res;
- }
-
// The next few routines are called only from assert expressions
// They verify that the built-in invokers process the correct raw data types.
private static boolean argumentTypesMatch(String sig, Object[] av) {
@@ -1151,113 +1147,6 @@
return super.hashCode();
}
- // Put the predefined NamedFunction invokers into the table.
- static void initializeInvokers() {
- for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
- if (!m.isStatic() || !m.isPackage()) continue;
- MethodType type = m.getMethodType();
- if (type.equals(INVOKER_METHOD_TYPE) &&
- m.getName().startsWith("invoke_")) {
- String sig = m.getName().substring("invoke_".length());
- int arity = LambdaForm.signatureArity(sig);
- MethodType srcType = MethodType.genericMethodType(arity);
- if (LambdaForm.signatureReturn(sig) == V_TYPE)
- srcType = srcType.changeReturnType(void.class);
- MethodTypeForm typeForm = srcType.form();
- typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m));
- }
- }
- }
-
- // The following are predefined NamedFunction invokers. The system must build
- // a separate invoker for each distinct signature.
- /** void return type invokers. */
- @Hidden
- static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(0, void.class, mh, a));
- mh.invokeBasic();
- return null;
- }
- @Hidden
- static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(1, void.class, mh, a));
- mh.invokeBasic(a[0]);
- return null;
- }
- @Hidden
- static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(2, void.class, mh, a));
- mh.invokeBasic(a[0], a[1]);
- return null;
- }
- @Hidden
- static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(3, void.class, mh, a));
- mh.invokeBasic(a[0], a[1], a[2]);
- return null;
- }
- @Hidden
- static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(4, void.class, mh, a));
- mh.invokeBasic(a[0], a[1], a[2], a[3]);
- return null;
- }
- @Hidden
- static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(5, void.class, mh, a));
- mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
- return null;
- }
- /** Object return type invokers. */
- @Hidden
- static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(0, mh, a));
- return mh.invokeBasic();
- }
- @Hidden
- static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(1, mh, a));
- return mh.invokeBasic(a[0]);
- }
- @Hidden
- static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(2, mh, a));
- return mh.invokeBasic(a[0], a[1]);
- }
- @Hidden
- static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(3, mh, a));
- return mh.invokeBasic(a[0], a[1], a[2]);
- }
- @Hidden
- static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(4, mh, a));
- return mh.invokeBasic(a[0], a[1], a[2], a[3]);
- }
- @Hidden
- static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(5, mh, a));
- return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
- }
- private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) {
- return arityCheck(arity, Object.class, mh, a);
- }
- private static boolean arityCheck(int arity, Class<?> rtype, MethodHandle mh, Object[] a) {
- assert(a.length == arity)
- : Arrays.asList(a.length, arity);
- assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype))
- : Arrays.asList(mh, rtype, arity);
- MemberName member = mh.internalMemberName();
- if (isInvokeBasic(member)) {
- assert(arity > 0);
- assert(a[0] instanceof MethodHandle);
- MethodHandle mh2 = (MethodHandle) a[0];
- assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype))
- : Arrays.asList(member, mh2, rtype, arity);
- }
- return true;
- }
-
static final MethodType INVOKER_METHOD_TYPE =
MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
@@ -1920,12 +1809,7 @@
DEBUG_NAME_COUNTERS = null;
}
- // Put this last, so that previous static inits can run before.
static {
- if (USE_PREDEFINED_INTERPRET_METHODS)
- computeInitialPreparedForms();
- NamedFunction.initializeInvokers();
-
// The Holder class will contain pre-generated forms resolved
// using MemberName.getFactory(). However, that doesn't initialize the
// class, which subtly breaks inlining etc. By forcing
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jul 05 22:08:15 2017 +0200
@@ -1745,6 +1745,13 @@
return GenerateJLIClassesHelper
.generateBasicFormsClassBytes(className);
}
+
+ @Override
+ public byte[] generateInvokersHolderClassBytes(final String className,
+ MethodType[] methodTypes) {
+ return GenerateJLIClassesHelper
+ .generateInvokersHolderClassBytes(className, methodTypes);
+ }
});
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Wed Jul 05 22:08:15 2017 +0200
@@ -46,6 +46,7 @@
static final boolean DUMP_CLASS_FILES;
static final boolean TRACE_INTERPRETER;
static final boolean TRACE_METHOD_LINKAGE;
+ static final boolean TRACE_RESOLVE;
static final int COMPILE_THRESHOLD;
static final boolean LOG_LF_COMPILATION_FAILURE;
static final int DONT_INLINE_THRESHOLD;
@@ -65,6 +66,8 @@
props.getProperty("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"));
TRACE_METHOD_LINKAGE = Boolean.parseBoolean(
props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"));
+ TRACE_RESOLVE = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.MethodHandle.TRACE_RESOLVE"));
COMPILE_THRESHOLD = Integer.parseInt(
props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0"));
LOG_LF_COMPILATION_FAILURE = Boolean.parseBoolean(
--- a/jdk/src/java.base/share/classes/java/net/HttpCookie.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/HttpCookie.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -233,7 +233,7 @@
// if not specify max-age, this cookie should be
// discarded when user agent is to be closed, but
// it is not expired.
- if (maxAge == MAX_AGE_UNSPECIFIED) return false;
+ if (maxAge < 0) return false;
long deltaSecond = (System.currentTimeMillis() - whenCreated) / 1000;
if (deltaSecond > maxAge)
@@ -952,7 +952,8 @@
String attrName,
String attrValue) {
if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) {
- cookie.setMaxAge(cookie.expiryDate2DeltaSeconds(attrValue));
+ long delta = cookie.expiryDate2DeltaSeconds(attrValue);
+ cookie.setMaxAge(delta > 0 ? delta : 0);
}
}
});
--- a/jdk/src/java.base/share/classes/java/time/Duration.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/Duration.java Wed Jul 05 22:08:15 2017 +0200
@@ -150,10 +150,12 @@
/**
* The pattern for parsing.
*/
- private static final Pattern PATTERN =
+ private static class Lazy {
+ static final Pattern PATTERN =
Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
"(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
Pattern.CASE_INSENSITIVE);
+ }
/**
* The number of seconds in the duration.
@@ -387,7 +389,7 @@
*/
public static Duration parse(CharSequence text) {
Objects.requireNonNull(text, "text");
- Matcher matcher = PATTERN.matcher(text);
+ Matcher matcher = Lazy.PATTERN.matcher(text);
if (matcher.matches()) {
// check for letter T but no time sections
if (!charMatch(text, matcher.start(3), matcher.end(3), 'T')) {
--- a/jdk/src/java.base/share/classes/java/time/ZoneOffset.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/ZoneOffset.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -375,15 +375,15 @@
} else if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0)) {
throw new DateTimeException("Zone offset minutes and seconds must have the same sign");
}
- if (Math.abs(minutes) > 59) {
- throw new DateTimeException("Zone offset minutes not in valid range: abs(value) " +
- Math.abs(minutes) + " is not in the range 0 to 59");
+ if (minutes < -59 || minutes > 59) {
+ throw new DateTimeException("Zone offset minutes not in valid range: value " +
+ minutes + " is not in the range -59 to 59");
}
- if (Math.abs(seconds) > 59) {
- throw new DateTimeException("Zone offset seconds not in valid range: abs(value) " +
- Math.abs(seconds) + " is not in the range 0 to 59");
+ if (seconds < -59 || seconds > 59) {
+ throw new DateTimeException("Zone offset seconds not in valid range: value " +
+ seconds + " is not in the range -59 to 59");
}
- if (Math.abs(hours) == 18 && (Math.abs(minutes) > 0 || Math.abs(seconds) > 0)) {
+ if (Math.abs(hours) == 18 && (minutes | seconds) != 0) {
throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
}
}
@@ -411,7 +411,7 @@
* @throws DateTimeException if the offset is not in the required range
*/
public static ZoneOffset ofTotalSeconds(int totalSeconds) {
- if (Math.abs(totalSeconds) > MAX_SECONDS) {
+ if (totalSeconds < -MAX_SECONDS || totalSeconds > MAX_SECONDS) {
throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
}
if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) {
@@ -696,11 +696,12 @@
* The comparison is "consistent with equals", as defined by {@link Comparable}.
*
* @param other the other date to compare to, not null
- * @return the comparator value, negative if less, postive if greater
+ * @return the comparator value, negative if less, positive if greater
* @throws NullPointerException if {@code other} is null
*/
@Override
public int compareTo(ZoneOffset other) {
+ // abs(totalSeconds) <= MAX_SECONDS, so no overflow can happen here
return other.totalSeconds - totalSeconds;
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Jul 05 22:08:15 2017 +0200
@@ -4566,7 +4566,10 @@
boolean modified = false;
// Use (c instanceof Set) as a hint that lookup in c is as
// efficient as this view
- if (c instanceof Set<?> && c.size() > map.table.length) {
+ Node<K,V>[] t;
+ if ((t = map.table) == null) {
+ return false;
+ } else if (c instanceof Set<?> && c.size() > t.length) {
for (Iterator<?> it = iterator(); it.hasNext(); ) {
if (c.contains(it.next())) {
it.remove();
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed Jul 05 22:08:15 2017 +0200
@@ -353,7 +353,7 @@
if (isMultiRelease) {
return true;
}
- if (MULTI_RELEASE_ENABLED && versionMajor != BASE_VERSION_MAJOR) {
+ if (MULTI_RELEASE_ENABLED) {
try {
checkForSpecialAttributes();
} catch (IOException io) {
@@ -644,7 +644,7 @@
return signers == null ? null : signers.clone();
}
JarFileEntry realEntry() {
- if (isMultiRelease()) {
+ if (isMultiRelease() && versionMajor != BASE_VERSION_MAJOR) {
String entryName = super.getName();
return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this);
}
@@ -960,7 +960,7 @@
hasClassPathAttribute = match(CLASSPATH_CHARS, b,
CLASSPATH_LASTOCC) != -1;
// is this a multi-release jar file
- if (MULTI_RELEASE_ENABLED && versionMajor != BASE_VERSION_MAJOR) {
+ if (MULTI_RELEASE_ENABLED) {
int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC);
if (i != -1) {
i += MULTIRELEASE_CHARS.length;
--- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java Wed Jul 05 22:08:15 2017 +0200
@@ -29,6 +29,7 @@
import java.util.jar.*;
import java.io.*;
import java.net.URL;
+import java.nio.file.*;
import java.security.*;
import java.security.Provider.Service;
@@ -206,7 +207,7 @@
static {
try {
- NULL_URL = new URL("http://null.sun.com/");
+ NULL_URL = new URL("http://null.oracle.com/");
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -243,83 +244,94 @@
}
}
+ // This is called from within an doPrivileged block.
private static void setupJurisdictionPolicies() throws Exception {
- String javaHomeDir = System.getProperty("java.home");
- String sep = File.separator;
- String pathToPolicyJar = javaHomeDir + sep + "lib" + sep +
- "security" + sep;
+
+ // Sanity check the crypto.policy Security property. Single
+ // directory entry, no pseudo-directories (".", "..", leading/trailing
+ // path separators). normalize()/getParent() will help later.
+ String cryptoPolicyProperty = Security.getProperty("crypto.policy");
+ Path cpPath = Paths.get(cryptoPolicyProperty);
+
+ if ((cryptoPolicyProperty == null) ||
+ (cpPath.getNameCount() != 1) ||
+ (cpPath.compareTo(cpPath.getFileName()) != 0)) {
+ throw new SecurityException(
+ "Invalid policy directory name format: " +
+ cryptoPolicyProperty);
+ }
- File exportJar = new File(pathToPolicyJar, "US_export_policy.jar");
- File importJar = new File(pathToPolicyJar, "local_policy.jar");
+ // Prepend java.home to get the full path. normalize() in
+ // case an extra "." or ".." snuck in somehow.
+ String javaHomeProperty = System.getProperty("java.home");
+ Path javaHomePolicyPath = Paths.get(javaHomeProperty, "conf",
+ "security", "policy").normalize();
+ Path cryptoPolicyPath = Paths.get(javaHomeProperty, "conf", "security",
+ "policy", cryptoPolicyProperty).normalize();
- if (!exportJar.exists() || !importJar.exists()) {
- throw new SecurityException
- ("Cannot locate policy or framework files!");
+ if (cryptoPolicyPath.getParent().compareTo(javaHomePolicyPath) != 0) {
+ throw new SecurityException(
+ "Invalid cryptographic jurisdiction policy directory path: " +
+ cryptoPolicyProperty);
+ }
+
+ if (!Files.isDirectory(cryptoPolicyPath)
+ || !Files.isReadable(cryptoPolicyPath)) {
+ throw new SecurityException(
+ "Can't read cryptographic policy directory: " +
+ cryptoPolicyProperty);
}
- // Read jurisdiction policies.
- CryptoPermissions defaultExport = new CryptoPermissions();
- CryptoPermissions exemptExport = new CryptoPermissions();
- loadPolicies(exportJar, defaultExport, exemptExport);
-
- CryptoPermissions defaultImport = new CryptoPermissions();
- CryptoPermissions exemptImport = new CryptoPermissions();
- loadPolicies(importJar, defaultImport, exemptImport);
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(
+ cryptoPolicyPath, "{default,exempt}_*.policy")) {
+ for (Path entry : stream) {
+ try (InputStream is = new BufferedInputStream(
+ Files.newInputStream(entry))) {
+ String filename = entry.getFileName().toString();
- // Merge the export and import policies for default applications.
- if (defaultExport.isEmpty() || defaultImport.isEmpty()) {
- throw new SecurityException("Missing mandatory jurisdiction " +
- "policy files");
- }
- defaultPolicy = defaultExport.getMinimum(defaultImport);
-
- // Merge the export and import policies for exempt applications.
- if (exemptExport.isEmpty()) {
- exemptPolicy = exemptImport.isEmpty() ? null : exemptImport;
- } else {
- exemptPolicy = exemptExport.getMinimum(exemptImport);
- }
- }
+ CryptoPermissions tmpPerms = new CryptoPermissions();
+ tmpPerms.load(is);
- /**
- * Load the policies from the specified file. Also checks that the
- * policies are correctly signed.
- */
- private static void loadPolicies(File jarPathName,
- CryptoPermissions defaultPolicy,
- CryptoPermissions exemptPolicy)
- throws Exception {
-
- JarFile jf = new JarFile(jarPathName);
-
- Enumeration<JarEntry> entries = jf.entries();
- while (entries.hasMoreElements()) {
- JarEntry je = entries.nextElement();
- InputStream is = null;
- try {
- if (je.getName().startsWith("default_")) {
- is = jf.getInputStream(je);
- defaultPolicy.load(is);
- } else if (je.getName().startsWith("exempt_")) {
- is = jf.getInputStream(je);
- exemptPolicy.load(is);
- } else {
- continue;
- }
- } finally {
- if (is != null) {
- is.close();
+ if (filename.startsWith("default_")) {
+ // Did we find a default perms?
+ defaultPolicy = ((defaultPolicy == null) ? tmpPerms :
+ defaultPolicy.getMinimum(tmpPerms));
+ } else if (filename.startsWith("exempt_")) {
+ // Did we find a exempt perms?
+ exemptPolicy = ((exemptPolicy == null) ? tmpPerms :
+ exemptPolicy.getMinimum(tmpPerms));
+ } else {
+ // This should never happen. newDirectoryStream
+ // should only throw return "{default,exempt}_*.policy"
+ throw new SecurityException(
+ "Unexpected jurisdiction policy files in : " +
+ cryptoPolicyProperty);
+ }
+ } catch (Exception e) {
+ throw new SecurityException(
+ "Couldn't parse jurisdiction policy files in: " +
+ cryptoPolicyProperty);
}
}
+ } catch (DirectoryIteratorException ex) {
+ // I/O error encountered during the iteration,
+ // the cause is an IOException
+ throw new SecurityException(
+ "Couldn't iterate through the jurisdiction policy files: " +
+ cryptoPolicyProperty);
+ }
- // Enforce the signer restraint, i.e. signer of JCE framework
- // jar should also be the signer of the two jurisdiction policy
- // jar files.
- ProviderVerifier.verifyPolicySigned(je.getCertificates());
+ // Must have a default policy
+ if ((defaultPolicy == null) || defaultPolicy.isEmpty()) {
+ throw new SecurityException(
+ "Missing mandatory jurisdiction policy files: " +
+ cryptoPolicyProperty);
}
- // Close and nullify the JarFile reference to help GC.
- jf.close();
- jf = null;
+
+ // If there was an empty exempt policy file, ignore it.
+ if ((exemptPolicy != null) && exemptPolicy.isEmpty()) {
+ exemptPolicy = null;
+ }
}
static CryptoPermissions getDefaultPolicy() {
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java Wed Jul 05 22:08:15 2017 +0200
@@ -47,8 +47,8 @@
private final JrtPath dir;
private final DirectoryStream.Filter<? super Path> filter;
- private volatile boolean isClosed;
- private volatile Iterator<Path> itr;
+ private boolean isClosed;
+ private Iterator<Path> itr;
JrtDirectoryStream(JrtPath dir,
DirectoryStream.Filter<? super java.nio.file.Path> filter)
@@ -73,24 +73,22 @@
throw new IllegalStateException(e);
}
return new Iterator<Path>() {
- private Path next;
@Override
- public synchronized boolean hasNext() {
- if (isClosed)
- return false;
- return itr.hasNext();
+ public boolean hasNext() {
+ synchronized (JrtDirectoryStream.this) {
+ if (isClosed)
+ return false;
+ return itr.hasNext();
+ }
}
@Override
- public synchronized Path next() {
- if (isClosed)
- throw new NoSuchElementException();
- return itr.next();
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public Path next() {
+ synchronized (JrtDirectoryStream.this) {
+ if (isClosed)
+ throw new NoSuchElementException();
+ return itr.next();
+ }
}
};
}
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java Wed Jul 05 22:08:15 2017 +0200
@@ -119,9 +119,7 @@
@Override
public Iterable<Path> getRootDirectories() {
- ArrayList<Path> dirs = new ArrayList<>();
- dirs.add(getRootPath());
- return dirs;
+ return Collections.singleton(getRootPath());
}
@Override
@@ -159,9 +157,7 @@
@Override
public final Iterable<FileStore> getFileStores() {
- ArrayList<FileStore> list = new ArrayList<>(1);
- list.add(getFileStore(getRootPath()));
- return list;
+ return Collections.singleton(getFileStore(getRootPath()));
}
private static final Set<String> supportedFileAttributeViews
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Wed Jul 05 22:08:15 2017 +0200
@@ -46,7 +46,7 @@
boolean isNative(Object mname);
/**
- * Returns a {@code byte[]} containing the bytecode for a class implementing
+ * Returns a {@code byte[]} representation of a class implementing
* DirectMethodHandle of each pairwise combination of {@code MethodType} and
* an {@code int} representing method type. Used by
* GenerateJLIClassesPlugin to generate such a class during the jlink phase.
@@ -55,7 +55,7 @@
MethodType[] methodTypes, int[] types);
/**
- * Returns a {@code byte[]} containing the bytecode for a class implementing
+ * Returns a {@code byte[]} representation of a class implementing
* DelegatingMethodHandles of each {@code MethodType} kind in the
* {@code methodTypes} argument. Used by GenerateJLIClassesPlugin to
* generate such a class during the jlink phase.
@@ -64,7 +64,7 @@
MethodType[] methodTypes);
/**
- * Returns a {@code byte[]} containing the bytecode for a BoundMethodHandle
+ * Returns a {@code byte[]} representation of {@code BoundMethodHandle}
* species class implementing the signature defined by {@code types}. Used
* by GenerateBMHClassesPlugin to enable generation of such classes during
* the jlink phase. Should do some added validation since this string may be
@@ -74,8 +74,15 @@
final String types);
/**
- * Returns a {@code byte[]} containing the bytecode for a class implementing
+ * Returns a {@code byte[]} representation of a class implementing
* the zero and identity forms of all {@code LambdaForm.BasicType}s.
*/
byte[] generateBasicFormsClassBytes(final String className);
+
+ /**
+ * Returns a {@code byte[]} representation of a class implementing
+ * the invoker forms for the set of supplied {@code methodTypes}.
+ */
+ byte[] generateInvokersHolderClassBytes(String className,
+ MethodType[] methodTypes);
}
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java Wed Jul 05 22:08:15 2017 +0200
@@ -253,7 +253,8 @@
public byte[] pad(byte[] data) throws BadPaddingException {
if (data.length > maxDataSize) {
throw new BadPaddingException("Data must be shorter than "
- + (maxDataSize + 1) + " bytes");
+ + (maxDataSize + 1) + " bytes but received "
+ + data.length + " bytes.");
}
switch (type) {
case PAD_NONE:
@@ -281,7 +282,9 @@
*/
public byte[] unpad(byte[] padded) throws BadPaddingException {
if (padded.length != paddedSize) {
- throw new BadPaddingException("Decryption error");
+ throw new BadPaddingException("Decryption error." +
+ "The padded array length (" + padded.length +
+ ") is not the specified padded size (" + paddedSize + ")");
}
switch (type) {
case PAD_NONE:
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Wed Jul 05 22:08:15 2017 +0200
@@ -493,7 +493,9 @@
if (protocolVersion.useTLS11PlusSpec()) {
if (newLen < blockSize) {
- throw new BadPaddingException("invalid explicit IV");
+ throw new BadPaddingException("The length after " +
+ "padding removal (" + newLen + ") should be larger " +
+ "than <" + blockSize + "> since explicit IV used");
}
}
}
@@ -504,7 +506,6 @@
}
}
-
/*
* Decrypts a block of data, returning the size of the
* resulting block if padding was required. position and limit
@@ -575,7 +576,9 @@
// check the explicit IV of TLS v1.1 or later
if (protocolVersion.useTLS11PlusSpec()) {
if (newLen < blockSize) {
- throw new BadPaddingException("invalid explicit IV");
+ throw new BadPaddingException("The length after " +
+ "padding removal (" + newLen + ") should be larger " +
+ "than <" + blockSize + "> since explicit IV used");
}
// reset the position to the end of the decrypted data
@@ -756,7 +759,9 @@
// so accept that as well
// v3 does not require any particular value for the other bytes
if (padLen > blockSize) {
- throw new BadPaddingException("Invalid SSLv3 padding");
+ throw new BadPaddingException("Padding length (" +
+ padLen + ") of SSLv3 message should not be bigger " +
+ "than the block size (" + blockSize + ")");
}
}
return newLen;
@@ -802,7 +807,9 @@
// so accept that as well
// v3 does not require any particular value for the other bytes
if (padLen > blockSize) {
- throw new BadPaddingException("Invalid SSLv3 padding");
+ throw new BadPaddingException("Padding length (" +
+ padLen + ") of SSLv3 message should not be bigger " +
+ "than the block size (" + blockSize + ")");
}
}
@@ -925,7 +932,10 @@
case AEAD_CIPHER:
if (bb.remaining() < (recordIvSize + tagSize)) {
throw new BadPaddingException(
- "invalid AEAD cipher fragment");
+ "Insufficient buffer remaining for AEAD cipher " +
+ "fragment (" + bb.remaining() + "). Needs to be " +
+ "more than or equal to IV size (" + recordIvSize +
+ ") + tag size (" + tagSize + ")");
}
// initialize the AEAD cipher for the unique IV
--- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java Wed Jul 05 22:08:15 2017 +0200
@@ -27,15 +27,8 @@
import java.io.IOException;
import java.io.ObjectInputStream;
-import java.lang.ref.SoftReference;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
-import java.util.List;
-import java.util.Locale;
import java.util.Map;
-import java.util.Set;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
@@ -80,8 +73,6 @@
private static final long ABBR_MASK = 0xf00L;
private static final int TRANSITION_NSHIFT = 12;
- private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar();
-
/**
* The raw GMT offset in milliseconds between this zone and GMT.
* Negative offsets are to the west of Greenwich. To obtain local
@@ -379,6 +370,7 @@
throw new IllegalArgumentException();
}
+ Gregorian gcal = CalendarSystem.getGregorianCalendar();
CalendarDate date = gcal.newCalendarDate(null);
date.setDate(year, month + 1, day);
if (gcal.validate(date) == false) {
--- a/jdk/src/java.base/share/conf/security/java.security Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/conf/security/java.security Wed Jul 05 22:08:15 2017 +0200
@@ -490,7 +490,7 @@
# property is set then those two properties are ignored.
#
# Example,
-# ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp"
+# ocsp.responderCertSubjectName=CN=OCSP Responder, O=XYZ Corp
#
# Issuer name of the OCSP responder's certificate
@@ -505,7 +505,7 @@
# property is ignored.
#
# Example,
-# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp"
+# ocsp.responderCertIssuerName=CN=Enterprise CA, O=XYZ Corp
#
# Serial number of the OCSP responder's certificate
@@ -803,3 +803,94 @@
# E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED \
# EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
# FFFFFFFF FFFFFFFF, 2}
+
+# Cryptographic Jurisdiction Policy defaults
+#
+# Due to the import control restrictions of some countries, the default
+# JCE policy files allow for strong but "limited" cryptographic key
+# lengths to be used. If your country's cryptographic regulations allow,
+# the "unlimited" strength policy files can be used instead, which contain
+# no restrictions on cryptographic strengths.
+#
+# If your country has restrictions that don't fit either "limited" or
+# "unlimited", an appropriate set of policy files should be created and
+# configured before using this distribution. The jurisdiction policy file
+# configuration must reflect the cryptographic restrictions appropriate
+# for your country.
+#
+# YOU ARE ADVISED TO CONSULT YOUR EXPORT/IMPORT CONTROL COUNSEL OR ATTORNEY
+# TO DETERMINE THE EXACT REQUIREMENTS.
+#
+# The policy files are flat text files organized into subdirectories of
+# <java-home>/conf/security/policy. Each directory contains a complete
+# set of policy files.
+#
+# The "crypto.policy" Security property controls the directory selection,
+# and thus the effective cryptographic policy.
+#
+# The default set of directories is:
+#
+# limited | unlimited
+#
+# however other directories can be created and configured.
+#
+# Within a directory, the effective policy is the combined minimum
+# permissions of the grant statements in the file(s) with the filename
+# pattern "default_*.policy". At least one grant is required. For
+# example:
+#
+# limited = Export (all) + Import (limited) = Limited
+# unlimited = Export (all) + Import (all) = Unlimited
+#
+# The effective exemption policy is the combined minimum permissions
+# of the grant statements in the file(s) with the filename pattern
+# "exempt_*.policy". Exemption grants are optional.
+#
+# limited = grants exemption permissions, by which the
+# effective policy can be circumvented.
+# e.g. KeyRecovery/Escrow/Weakening.
+#
+# Please see the JCA documentation for additional information on these
+# files and formats.
+crypto.policy=crypto.policydir-tbd
+
+#
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
+#
+# Policy:
+# Constraint {"," Constraint }
+# Constraint:
+# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+# ReferenceUriSchemeConstraint | OtherConstraint
+# AlgConstraint
+# "disallowAlg" Uri
+# MaxTransformsConstraint:
+# "maxTransforms" Integer
+# MaxReferencesConstraint:
+# "maxReferences" Integer
+# ReferenceUriSchemeConstraint:
+# "disallowReferenceUriSchemes" String { String }
+# OtherConstraint:
+# "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. If the MaxTransformsConstraint or MaxReferencesConstraint is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+jdk.xml.dsig.secureValidationPolicy=\
+ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+ maxTransforms 5,\
+ maxReferences 30,\
+ disallowReferenceUriSchemes file http https,\
+ noDuplicateIds,\
+ noRetrievalMethodLoops
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/conf/security/policy/README.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,35 @@
+
+ Java(TM) Cryptography Extension Policy Files
+ for the Java(TM) Platform, Standard Edition Runtime Environment
+
+ README
+------------------------------------------------------------------------
+
+
+The JCE architecture allows flexible cryptographic strength to be
+configured via the jurisdiction policy files contained within these
+directories.
+
+Due to import control restrictions of some countries, the default
+JCE policy files bundled in this Java Runtime Environment allow
+for strong but "limited" cryptographic strengths. For convenience,
+this build also contains the "unlimited strength" policy files which
+contain no restrictions on cryptographic strengths, but they must be
+specifically activated by updating the "crypto.policy" Security property
+(e.g. <java-home>/conf/security/java.security) to point to the appropriate
+directory.
+
+Each subdirectory contains a complete policy configuration, and additional
+subdirectories can be added/removed to reflect local regulations.
+
+JCE for Java SE has been through the U.S. export review process. The JCE
+framework, along with the various JCE providers that come standard with it
+(SunJCE, SunEC, SunPKCS11, SunMSCAPI, etc), is exportable from the
+United States.
+
+You are advised to consult your export/import control counsel or attorney
+to determine the exact requirements of your location, and what policy
+settings should be used.
+
+Please see The Java(TM) Cryptography Architecture (JCA) Reference
+Guide and the java.security file for more information.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/conf/security/policy/limited/default_US_export.policy Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,6 @@
+// Default US Export policy file.
+
+grant {
+ // There is no restriction to any algorithms.
+ permission javax.crypto.CryptoAllPermission;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/conf/security/policy/limited/default_local.policy Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,14 @@
+// Some countries have import limits on crypto strength. This policy file
+// is worldwide importable.
+
+grant {
+ permission javax.crypto.CryptoPermission "DES", 64;
+ permission javax.crypto.CryptoPermission "DESede", *;
+ permission javax.crypto.CryptoPermission "RC2", 128,
+ "javax.crypto.spec.RC2ParameterSpec", 128;
+ permission javax.crypto.CryptoPermission "RC4", 128;
+ permission javax.crypto.CryptoPermission "RC5", 128,
+ "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
+ permission javax.crypto.CryptoPermission "RSA", *;
+ permission javax.crypto.CryptoPermission *, 128;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/conf/security/policy/limited/exempt_local.policy Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,13 @@
+// Some countries have import limits on crypto strength, but may allow for
+// these exemptions if the exemption mechanism is used.
+
+grant {
+ // There is no restriction to any algorithms if KeyRecovery is enforced.
+ permission javax.crypto.CryptoPermission *, "KeyRecovery";
+
+ // There is no restriction to any algorithms if KeyEscrow is enforced.
+ permission javax.crypto.CryptoPermission *, "KeyEscrow";
+
+ // There is no restriction to any algorithms if KeyWeakening is enforced.
+ permission javax.crypto.CryptoPermission *, "KeyWeakening";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/conf/security/policy/unlimited/default_US_export.policy Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,6 @@
+// Default US Export policy file.
+
+grant {
+ // There is no restriction to any algorithms.
+ permission javax.crypto.CryptoAllPermission;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/conf/security/policy/unlimited/default_local.policy Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,6 @@
+// Country-specific policy file for countries with no limits on crypto strength.
+
+grant {
+ // There is no restriction to any algorithms.
+ permission javax.crypto.CryptoAllPermission;
+};
--- a/jdk/src/java.base/share/lib/security/default.policy Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/share/lib/security/default.policy Wed Jul 05 22:08:15 2017 +0200
@@ -72,6 +72,8 @@
"removeProviderProperty.XMLDSig";
permission java.security.SecurityPermission
"com.sun.org.apache.xml.internal.security.register";
+ permission java.security.SecurityPermission
+ "getProperty.jdk.xml.dsig.secureValidationPolicy";
};
grant codeBase "jrt:/java.xml.ws" {
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java Wed Jul 05 22:08:15 2017 +0200
@@ -252,6 +252,21 @@
return new UnixPath(getFileSystem(), new byte[0]);
}
+
+ // return true if this path has "." or ".."
+ private boolean hasDotOrDotDot() {
+ int n = getNameCount();
+ for (int i=0; i<n; i++) {
+ byte[] bytes = getName(i).path;
+ if ((bytes.length == 1 && bytes[0] == '.'))
+ return true;
+ if ((bytes.length == 2 && bytes[0] == '.') && bytes[1] == '.') {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public UnixFileSystem getFileSystem() {
return fs;
@@ -405,80 +420,94 @@
@Override
public UnixPath relativize(Path obj) {
- UnixPath other = toUnixPath(obj);
- if (other.equals(this))
+ UnixPath child = toUnixPath(obj);
+ if (child.equals(this))
return emptyPath();
// can only relativize paths of the same type
- if (this.isAbsolute() != other.isAbsolute())
+ if (this.isAbsolute() != child.isAbsolute())
throw new IllegalArgumentException("'other' is different type of Path");
// this path is the empty path
if (this.isEmpty())
- return other;
+ return child;
- int bn = this.getNameCount();
- int cn = other.getNameCount();
+ UnixPath base = this;
+ if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
+ base = base.normalize();
+ child = child.normalize();
+ }
+
+ int baseCount = base.getNameCount();
+ int childCount = child.getNameCount();
// skip matching names
- int n = (bn > cn) ? cn : bn;
+ int n = Math.min(baseCount, childCount);
int i = 0;
while (i < n) {
- if (!this.getName(i).equals(other.getName(i)))
+ if (!base.getName(i).equals(child.getName(i)))
break;
i++;
}
- int dotdots = bn - i;
- if (i < cn) {
- // remaining name components in other
- UnixPath remainder = other.subpath(i, cn);
- if (dotdots == 0)
- return remainder;
+ // remaining elements in child
+ UnixPath childRemaining;
+ boolean isChildEmpty;
+ if (i == childCount) {
+ childRemaining = emptyPath();
+ isChildEmpty = true;
+ } else {
+ childRemaining = child.subpath(i, childCount);
+ isChildEmpty = childRemaining.isEmpty();
+ }
+
+ // matched all of base
+ if (i == baseCount) {
+ return childRemaining;
+ }
- // other is the empty path
- boolean isOtherEmpty = other.isEmpty();
+ // the remainder of base cannot contain ".."
+ UnixPath baseRemaining = base.subpath(i, baseCount);
+ if (baseRemaining.hasDotOrDotDot()) {
+ throw new IllegalArgumentException("Unable to compute relative "
+ + " path from " + this + " to " + obj);
+ }
+ if (baseRemaining.isEmpty())
+ return childRemaining;
+
+ // number of ".." needed
+ int dotdots = baseRemaining.getNameCount();
+ if (dotdots == 0) {
+ return childRemaining;
+ }
- // result is a "../" for each remaining name in base
- // followed by the remaining names in other. If the remainder is
- // the empty path then we don't add the final trailing slash.
- int len = dotdots*3 + remainder.path.length;
- if (isOtherEmpty) {
- assert remainder.isEmpty();
- len--;
+ // result is a "../" for each remaining name in base followed by the
+ // remaining names in child. If the remainder is the empty path
+ // then we don't add the final trailing slash.
+ int len = dotdots*3 + childRemaining.path.length;
+ if (isChildEmpty) {
+ assert childRemaining.isEmpty();
+ len--;
+ }
+ byte[] result = new byte[len];
+ int pos = 0;
+ while (dotdots > 0) {
+ result[pos++] = (byte)'.';
+ result[pos++] = (byte)'.';
+ if (isChildEmpty) {
+ if (dotdots > 1) result[pos++] = (byte)'/';
+ } else {
+ result[pos++] = (byte)'/';
}
- byte[] result = new byte[len];
- int pos = 0;
- while (dotdots > 0) {
- result[pos++] = (byte)'.';
- result[pos++] = (byte)'.';
- if (isOtherEmpty) {
- if (dotdots > 1) result[pos++] = (byte)'/';
- } else {
- result[pos++] = (byte)'/';
- }
- dotdots--;
- }
- System.arraycopy(remainder.path, 0, result, pos, remainder.path.length);
- return new UnixPath(getFileSystem(), result);
- } else {
- // no remaining names in other so result is simply a sequence of ".."
- byte[] result = new byte[dotdots*3 - 1];
- int pos = 0;
- while (dotdots > 0) {
- result[pos++] = (byte)'.';
- result[pos++] = (byte)'.';
- // no tailing slash at the end
- if (dotdots > 1)
- result[pos++] = (byte)'/';
- dotdots--;
- }
- return new UnixPath(getFileSystem(), result);
+ dotdots--;
}
+ System.arraycopy(childRemaining.path,0, result, pos,
+ childRemaining.path.length);
+ return new UnixPath(getFileSystem(), result);
}
@Override
- public Path normalize() {
+ public UnixPath normalize() {
final int count = getNameCount();
if (count == 0 || isEmpty())
return this;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java Wed Jul 05 22:08:15 2017 +0200
@@ -375,57 +375,108 @@
return (WindowsPath)path;
}
+ // return true if this path has "." or ".."
+ private boolean hasDotOrDotDot() {
+ int n = getNameCount();
+ for (int i=0; i<n; i++) {
+ String name = elementAsString(i);
+ if (name.length() == 1 && name.charAt(0) == '.')
+ return true;
+ if (name.length() == 2
+ && name.charAt(0) == '.' && name.charAt(1) == '.')
+ return true;
+ }
+ return false;
+ }
+
@Override
public WindowsPath relativize(Path obj) {
- WindowsPath other = toWindowsPath(obj);
- if (this.equals(other))
+ WindowsPath child = toWindowsPath(obj);
+ if (this.equals(child))
return emptyPath();
// can only relativize paths of the same type
- if (this.type != other.type)
+ if (this.type != child.type)
throw new IllegalArgumentException("'other' is different type of Path");
// can only relativize paths if root component matches
- if (!this.root.equalsIgnoreCase(other.root))
+ if (!this.root.equalsIgnoreCase(child.root))
throw new IllegalArgumentException("'other' has different root");
// this path is the empty path
if (this.isEmpty())
- return other;
+ return child;
+
- int bn = this.getNameCount();
- int cn = other.getNameCount();
+ WindowsPath base = this;
+ if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
+ base = base.normalize();
+ child = child.normalize();
+ }
+
+ int baseCount = base.getNameCount();
+ int childCount = child.getNameCount();
// skip matching names
- int n = (bn > cn) ? cn : bn;
+ int n = Math.min(baseCount, childCount);
int i = 0;
while (i < n) {
- if (!this.getName(i).equals(other.getName(i)))
+ if (!base.getName(i).equals(child.getName(i)))
break;
i++;
}
- // append ..\ for remaining names in the base
+ // remaining elements in child
+ WindowsPath childRemaining;
+ boolean isChildEmpty;
+ if (i == childCount) {
+ childRemaining = emptyPath();
+ isChildEmpty = true;
+ } else {
+ childRemaining = child.subpath(i, childCount);
+ isChildEmpty = childRemaining.isEmpty();
+ }
+
+ // matched all of base
+ if (i == baseCount) {
+ return childRemaining;
+ }
+
+ // the remainder of base cannot contain ".."
+ WindowsPath baseRemaining = base.subpath(i, baseCount);
+ if (baseRemaining.hasDotOrDotDot()) {
+ throw new IllegalArgumentException("Unable to compute relative "
+ + " path from " + this + " to " + obj);
+ }
+ if (baseRemaining.isEmpty())
+ return childRemaining;
+
+ // number of ".." needed
+ int dotdots = baseRemaining.getNameCount();
+ if (dotdots == 0) {
+ return childRemaining;
+ }
+
StringBuilder result = new StringBuilder();
- for (int j=i; j<bn; j++) {
+ for (int j=0; j<dotdots; j++) {
result.append("..\\");
}
// append remaining names in child
- if (!other.isEmpty()) {
- for (int j=i; j<cn; j++) {
- result.append(other.getName(j).toString());
+ if (!isChildEmpty) {
+ for (int j=0; j<childRemaining.getNameCount(); j++) {
+ result.append(childRemaining.getName(j).toString());
result.append("\\");
}
}
- // drop trailing slash in result
+ // drop trailing slash
result.setLength(result.length()-1);
return createFromNormalizedPath(getFileSystem(), result.toString());
}
@Override
- public Path normalize() {
+ public WindowsPath normalize() {
final int count = getNameCount();
if (count == 0 || isEmpty())
return this;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java Wed Jul 05 22:08:15 2017 +0200
@@ -390,35 +390,27 @@
for (int i=1; i <= retries; i++) {
String proto = useTCP?"TCP":"UDP";
- try (NetClient kdcClient = NetClient.getInstance(
- proto, kdc, port, timeout)) {
- if (DEBUG) {
- System.out.println(">>> KDCCommunication: kdc=" + kdc
+ if (DEBUG) {
+ System.out.println(">>> KDCCommunication: kdc=" + kdc
+ " " + proto + ":"
+ port + ", timeout="
+ timeout
+ ",Attempt =" + i
+ ", #bytes=" + obuf.length);
+ }
+ try (NetClient kdcClient = NetClient.getInstance(
+ proto, kdc, port, timeout)) {
+ kdcClient.send(obuf);
+ ibuf = kdcClient.receive();
+ break;
+ } catch (SocketTimeoutException se) {
+ if (DEBUG) {
+ System.out.println ("SocketTimeOutException with " +
+ "attempt: " + i);
}
- try {
- /*
- * Send the data to the kdc.
- */
- kdcClient.send(obuf);
- /*
- * And get a response.
- */
- ibuf = kdcClient.receive();
- break;
- } catch (SocketTimeoutException se) {
- if (DEBUG) {
- System.out.println ("SocketTimeOutException with " +
- "attempt: " + i);
- }
- if (i == retries) {
- ibuf = null;
- throw se;
- }
+ if (i == retries) {
+ ibuf = null;
+ throw se;
}
}
}
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3204,7 +3204,6 @@
* this method is called on a closed <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @since 1.4
*/
public void setNull(String parameterName, int sqlType) throws SQLException {
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3240,7 +3239,6 @@
* this method is called on a closed <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @since 1.4
*/
public void setNull (String parameterName, int sqlType, String typeName)
throws SQLException{
@@ -3259,7 +3257,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setBoolean(String parameterName, boolean x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3277,7 +3274,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setByte(String parameterName, byte x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3295,7 +3291,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setShort(String parameterName, short x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3313,7 +3308,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setInt(String parameterName, int x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3332,7 +3326,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setLong(String parameterName, long x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3350,7 +3343,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setFloat(String parameterName, float x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3368,7 +3360,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setDouble(String parameterName, double x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3387,7 +3378,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3408,7 +3398,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setString(String parameterName, String x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3428,7 +3417,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setBytes(String parameterName, byte x[]) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3447,7 +3435,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setTimestamp(String parameterName, java.sql.Timestamp x)
throws SQLException{
@@ -3474,7 +3461,6 @@
* this method is called on a closed <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @since 1.4
*/
public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
throws SQLException{
@@ -3500,7 +3486,6 @@
* this method is called on a closed <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @since 1.4
*/
public void setBinaryStream(String parameterName, java.io.InputStream x,
int length) throws SQLException{
@@ -3528,7 +3513,6 @@
* this method is called on a closed <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @since 1.4
*/
public void setCharacterStream(String parameterName,
java.io.Reader reader,
@@ -3684,7 +3668,6 @@
* this data type
* @see Types
* @see #getParams
- * @since 1.4
*/
public void setObject(String parameterName, Object x, int targetSqlType, int scale)
throws SQLException{
@@ -3710,7 +3693,6 @@
* or <code>STRUCT</code> data type and the JDBC driver does not support
* this data type
* @see #getParams
- * @since 1.4
*/
public void setObject(String parameterName, Object x, int targetSqlType)
throws SQLException{
@@ -3751,7 +3733,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setObject(String parameterName, Object x) throws SQLException{
throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -4024,7 +4005,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setDate(String parameterName, java.sql.Date x)
throws SQLException {
@@ -4050,7 +4030,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setDate(String parameterName, java.sql.Date x, Calendar cal)
throws SQLException {
@@ -4069,7 +4048,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setTime(String parameterName, java.sql.Time x)
throws SQLException {
@@ -4095,7 +4073,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setTime(String parameterName, java.sql.Time x, Calendar cal)
throws SQLException {
@@ -4121,7 +4098,6 @@
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #getParams
- * @since 1.4
*/
public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
throws SQLException {
@@ -4459,7 +4435,6 @@
* @exception SQLException if a database access error occurs or
* this method is called on a closed <code>PreparedStatement</code>
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
- * @since 1.4
*/
public void setURL(int parameterIndex, java.net.URL x) throws SQLException {
throw new SQLFeatureNotSupportedException("Feature not supported");
--- a/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java Wed Jul 05 22:08:15 2017 +0200
@@ -57,7 +57,6 @@
* logging is disabled
* @exception java.sql.SQLException if a database access error occurs
* @see #setLogWriter
- * @since 1.4
*/
java.io.PrintWriter getLogWriter() throws SQLException;
@@ -79,7 +78,6 @@
* @param out the new log writer; to disable logging, set to null
* @exception SQLException if a database access error occurs
* @see #getLogWriter
- * @since 1.4
*/
void setLogWriter(java.io.PrintWriter out) throws SQLException;
@@ -94,7 +92,6 @@
* @param seconds the data source login time limit
* @exception SQLException if a database access error occurs.
* @see #getLoginTimeout
- * @since 1.4
*/
void setLoginTimeout(int seconds) throws SQLException;
@@ -109,7 +106,6 @@
* @return the data source login time limit
* @exception SQLException if a database access error occurs.
* @see #setLoginTimeout
- * @since 1.4
*/
int getLoginTimeout() throws SQLException;
--- a/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java Wed Jul 05 22:08:15 2017 +0200
@@ -72,6 +72,34 @@
PooledConnection getPooledConnection(String user, String password)
throws SQLException;
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ java.io.PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ void setLogWriter(java.io.PrintWriter out) throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ void setLoginTimeout(int seconds) throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ int getLoginTimeout() throws SQLException;
+
//------------------------- JDBC 4.3 -----------------------------------
/**
--- a/jdk/src/java.sql/share/classes/javax/sql/DataSource.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/DataSource.java Wed Jul 05 22:08:15 2017 +0200
@@ -109,6 +109,34 @@
Connection getConnection(String username, String password)
throws SQLException;
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ java.io.PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ void setLogWriter(java.io.PrintWriter out) throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ void setLoginTimeout(int seconds) throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ int getLoginTimeout() throws SQLException;
+
// JDBC 4.3
/**
--- a/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java Wed Jul 05 22:08:15 2017 +0200
@@ -81,7 +81,35 @@
XAConnection getXAConnection(String user, String password)
throws SQLException;
- // JDBC 4.3
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ java.io.PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ void setLogWriter(java.io.PrintWriter out) throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ void setLoginTimeout(int seconds) throws SQLException;
+
+ /**
+ * {@inheritDoc}
+ * @since 1.4
+ */
+ @Override
+ int getLoginTimeout() throws SQLException;
+
+ // JDBC 4.3
/**
* Creates a new {@code XAConnectionBuilder} instance
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java Wed Jul 05 22:08:15 2017 +0200
@@ -150,7 +150,7 @@
this.macAlgorithm.init(secretKey);
} catch (InvalidKeyException ex) {
// reinstantiate Mac object to work around bug in JDK
- // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ // see: http://bugs.java.com/view_bug.do?bug_id=4953555
Mac mac = this.macAlgorithm;
try {
this.macAlgorithm = Mac.getInstance(macAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java Wed Jul 05 22:08:15 2017 +0200
@@ -112,7 +112,7 @@
this.signatureAlgorithm.initVerify((PublicKey) publicKey);
} catch (InvalidKeyException ex) {
// reinstantiate Signature object to work around bug in JDK
- // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ // see: http://bugs.java.com/view_bug.do?bug_id=4953555
Signature sig = this.signatureAlgorithm;
try {
this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java Wed Jul 05 22:08:15 2017 +0200
@@ -139,7 +139,7 @@
this.signatureAlgorithm.initVerify((PublicKey) publicKey);
} catch (InvalidKeyException ex) {
// reinstantiate Signature object to work around bug in JDK
- // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ // see: http://bugs.java.com/view_bug.do?bug_id=4953555
Signature sig = this.signatureAlgorithm;
try {
this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java Wed Jul 05 22:08:15 2017 +0200
@@ -252,7 +252,7 @@
this.signatureAlgorithm.initVerify((PublicKey) publicKey);
} catch (InvalidKeyException ex) {
// reinstantiate Signature object to work around bug in JDK
- // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ // see: http://bugs.java.com/view_bug.do?bug_id=4953555
Signature sig = this.signatureAlgorithm;
try {
this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java Wed Jul 05 22:08:15 2017 +0200
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $
@@ -38,7 +38,6 @@
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
import com.sun.org.apache.xml.internal.security.transforms.Transform;
-import com.sun.org.apache.xml.internal.security.transforms.Transforms;
import javax.xml.crypto.*;
import javax.xml.crypto.dom.DOMCryptoContext;
@@ -150,7 +149,7 @@
if (Utils.secureValidation(xc)) {
String algorithm = getAlgorithm();
- if (Transforms.TRANSFORM_XSLT.equals(algorithm)) {
+ if (Policy.restrictAlg(algorithm)) {
throw new TransformException(
"Transform " + algorithm + " is forbidden when secure validation is enabled"
);
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java Wed Jul 05 22:08:15 2017 +0200
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -110,9 +110,10 @@
localName + ", expected Reference");
}
refs.add(new DOMReference(refElem, context, provider));
- if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) {
- String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " "
- + "references per Manifest are allowed with secure validation";
+ if (secVal && Policy.restrictNumReferences(refs.size())) {
+ String error = "A maximum of " + Policy.maxReferences()
+ + " references per Manifest are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
refElem = DOMUtils.getNextSiblingElement(refElem);
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java Wed Jul 05 22:08:15 2017 +0200
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* ===========================================================================
@@ -51,7 +51,6 @@
import org.w3c.dom.Node;
import org.jcp.xml.dsig.internal.DigesterOutputStream;
-import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
import com.sun.org.apache.xml.internal.security.utils.Base64;
@@ -67,11 +66,6 @@
implements Reference, DOMURIReference {
/**
- * The maximum number of transforms per reference, if secure validation is enabled.
- */
- public static final int MAXIMUM_TRANSFORM_COUNT = 5;
-
- /**
* Look up useC14N11 system property. If true, an explicit C14N11 transform
* will be added if necessary when generating the signature. See section
* 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info.
@@ -208,9 +202,10 @@
}
transforms.add
(new DOMTransform(transformElem, context, provider));
- if (secVal && (transforms.size() > MAXIMUM_TRANSFORM_COUNT)) {
- String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " "
- + "transforms per Reference are allowed with secure validation";
+ if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+ String error = "A maximum of " + Policy.maxTransforms()
+ + " transforms per Reference are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -227,10 +222,10 @@
Element dmElem = nextSibling;
this.digestMethod = DOMDigestMethod.unmarshal(dmElem);
String digestMethodAlgorithm = this.digestMethod.getAlgorithm();
- if (secVal
- && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) {
+ if (secVal && Policy.restrictAlg(digestMethodAlgorithm)) {
throw new MarshalException(
- "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled"
+ "It is forbidden to use algorithm " + digestMethodAlgorithm +
+ " when secure validation is enabled"
);
}
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Wed Jul 05 22:08:15 2017 +0200
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* ===========================================================================
@@ -149,9 +149,10 @@
}
transforms.add
(new DOMTransform(transformElem, context, provider));
- if (secVal && (transforms.size() > DOMReference.MAXIMUM_TRANSFORM_COUNT)) {
- String error = "A maxiumum of " + DOMReference.MAXIMUM_TRANSFORM_COUNT + " "
- + "transforms per Reference are allowed with secure validation";
+ if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+ String error = "A maximum of " + Policy.maxTransforms()
+ + " transforms per Reference are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -238,7 +239,8 @@
}
// guard against RetrievalMethod loops
- if ((data instanceof NodeSetData) && Utils.secureValidation(context)) {
+ if ((data instanceof NodeSetData) && Utils.secureValidation(context)
+ && Policy.restrictRetrievalMethodLoops()) {
NodeSetData<?> nsd = (NodeSetData<?>)data;
Iterator<?> i = nsd.iterator();
if (i.hasNext()) {
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java Wed Jul 05 22:08:15 2017 +0200
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -45,7 +45,6 @@
import org.w3c.dom.Node;
import com.sun.org.apache.xml.internal.security.utils.Base64;
-import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
/**
@@ -55,22 +54,9 @@
*/
public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
- /**
- * The maximum number of references per Manifest, if secure validation is enabled.
- */
- public static final int MAXIMUM_REFERENCE_COUNT = 30;
-
private static java.util.logging.Logger log =
java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
- /** Signature - NOT Recommended RSAwithMD5 */
- private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
- Constants.MoreAlgorithmsSpecNS + "rsa-md5";
-
- /** HMAC - NOT Recommended HMAC-MD5 */
- private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
- Constants.MoreAlgorithmsSpecNS + "hmac-md5";
-
private List<Reference> references;
private CanonicalizationMethod canonicalizationMethod;
private SignatureMethod signatureMethod;
@@ -158,10 +144,10 @@
boolean secVal = Utils.secureValidation(context);
String signatureMethodAlgorithm = signatureMethod.getAlgorithm();
- if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm)
- || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) {
+ if (secVal && Policy.restrictAlg(signatureMethodAlgorithm)) {
throw new MarshalException(
- "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled"
+ "It is forbidden to use algorithm " + signatureMethodAlgorithm +
+ " when secure validation is enabled"
);
}
@@ -179,9 +165,10 @@
}
refList.add(new DOMReference(refElem, context, provider));
- if (secVal && (refList.size() > MAXIMUM_REFERENCE_COUNT)) {
- String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " "
- + "references per Manifest are allowed with secure validation";
+ if (secVal && Policy.restrictNumReferences(refList.size())) {
+ String error = "A maximum of " + Policy.maxReferences()
+ + " references per Manifest are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
refElem = DOMUtils.getNextSiblingElement(refElem);
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java Wed Jul 05 22:08:15 2017 +0200
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMURIDereferencer.java 1231033 2012-01-13 12:12:12Z coheigea $
@@ -73,6 +73,11 @@
boolean secVal = Utils.secureValidation(context);
+ if (secVal && Policy.restrictReferenceUriScheme(uri)) {
+ throw new URIReferenceException(
+ "Uri " + uri + " is forbidden when secure validation is enabled");
+ }
+
// Check if same-document URI and already registered on the context
if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') {
String id = uri.substring(1);
@@ -83,12 +88,19 @@
id = id.substring(i1+1, i2);
}
- Node referencedElem = dcc.getElementById(id);
+ // check if element is registered by Id
+ Node referencedElem = uriAttr.getOwnerDocument().getElementById(id);
+ if (referencedElem == null) {
+ // see if element is registered in DOMCryptoContext
+ referencedElem = dcc.getElementById(id);
+ }
if (referencedElem != null) {
- if (secVal) {
+ if (secVal && Policy.restrictDuplicateIds()) {
Element start = referencedElem.getOwnerDocument().getDocumentElement();
if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) {
- String error = "Multiple Elements with the same ID " + id + " were detected";
+ String error = "Multiple Elements with the same ID "
+ + id + " detected when secure validation"
+ + " is enabled";
throw new URIReferenceException(error);
}
}
@@ -110,9 +122,9 @@
try {
ResourceResolver apacheResolver =
- ResourceResolver.getInstance(uriAttr, baseURI, secVal);
+ ResourceResolver.getInstance(uriAttr, baseURI, false);
XMLSignatureInput in = apacheResolver.resolve(uriAttr,
- baseURI, secVal);
+ baseURI, false);
if (in.isOctetStream()) {
return new ApacheOctetStreamData(in);
} else {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jcp.xml.dsig.internal.dom;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * The secure validation policy as specified by the
+ * jdk.xml.dsig.secureValidationPolicy security property.
+ */
+public final class Policy {
+
+ // all restrictions are initialized to be unconstrained
+ private static Set<URI> disallowedAlgs = new HashSet<>();
+ private static int maxTrans = Integer.MAX_VALUE;
+ private static int maxRefs = Integer.MAX_VALUE;
+ private static Set<String> disallowedRefUriSchemes = new HashSet<>();
+ private static boolean noDuplicateIds = false;
+ private static boolean noRMLoops = false;
+
+ static {
+ try {
+ initialize();
+ } catch (Exception e) {
+ throw new SecurityException(
+ "Cannot initialize the secure validation policy", e);
+ }
+ }
+
+ private Policy() {}
+
+ private static void initialize() {
+ String prop =
+ AccessController.doPrivileged((PrivilegedAction<String>) () ->
+ Security.getProperty("jdk.xml.dsig.secureValidationPolicy"));
+ if (prop == null || prop.isEmpty()) {
+ // no policy specified, so don't enforce any restrictions
+ return;
+ }
+ String[] entries = prop.split(",");
+ for (String entry : entries) {
+ String[] tokens = entry.split("\\s");
+ String type = tokens[0];
+ switch(type) {
+ case "disallowAlg":
+ if (tokens.length != 2) {
+ error(entry);
+ }
+ disallowedAlgs.add(URI.create(tokens[1]));
+ break;
+ case "maxTransforms":
+ if (tokens.length != 2) {
+ error(entry);
+ }
+ maxTrans = Integer.parseUnsignedInt(tokens[1]);
+ break;
+ case "maxReferences":
+ if (tokens.length != 2) {
+ error(entry);
+ }
+ maxRefs = Integer.parseUnsignedInt(tokens[1]);
+ break;
+ case "disallowReferenceUriSchemes":
+ if (tokens.length == 1) {
+ error(entry);
+ }
+ for (int i = 1; i < tokens.length; i++) {
+ String scheme = tokens[i];
+ disallowedRefUriSchemes.add(
+ scheme.toLowerCase(Locale.ROOT));
+ }
+ break;
+ case "noDuplicateIds":
+ if (tokens.length != 1) {
+ error(entry);
+ }
+ noDuplicateIds = true;
+ break;
+ case "noRetrievalMethodLoops":
+ if (tokens.length != 1) {
+ error(entry);
+ }
+ noRMLoops = true;
+ break;
+ default:
+ error(entry);
+ }
+ }
+ }
+
+ public static boolean restrictAlg(String alg) {
+ try {
+ URI uri = new URI(alg);
+ return disallowedAlgs.contains(uri);
+ } catch (URISyntaxException use) {
+ return false;
+ }
+ }
+
+ public static boolean restrictNumTransforms(int numTrans) {
+ return (numTrans > maxTrans);
+ }
+
+ public static boolean restrictNumReferences(int numRefs) {
+ return (numRefs > maxRefs);
+ }
+
+ public static boolean restrictReferenceUriScheme(String uri) {
+ if (uri != null) {
+ String scheme = java.net.URI.create(uri).getScheme();
+ if (scheme != null) {
+ return disallowedRefUriSchemes.contains(
+ scheme.toLowerCase(Locale.ROOT));
+ }
+ }
+ return false;
+ }
+
+ public static boolean restrictDuplicateIds() {
+ return noDuplicateIds;
+ }
+
+ public static boolean restrictRetrievalMethodLoops() {
+ return noRMLoops;
+ }
+
+ public static Set<URI> disabledAlgs() {
+ return Collections.<URI>unmodifiableSet(disallowedAlgs);
+ }
+
+ public static int maxTransforms() {
+ return maxTrans;
+ }
+
+ public static int maxReferences() {
+ return maxRefs;
+ }
+
+ public static Set<String> disabledReferenceUriSchemes() {
+ return Collections.<String>unmodifiableSet(disallowedRefUriSchemes);
+ }
+
+ private static void error(String entry) {
+ throw new IllegalArgumentException(
+ "Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry);
+ }
+}
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java Wed Jul 05 22:08:15 2017 +0200
@@ -358,7 +358,9 @@
System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs);
tmpBuffer = p11.C_Sign(session.id(), tmpBuffer);
if (tmpBuffer.length > outLen) {
- throw new BadPaddingException("Output buffer too small");
+ throw new BadPaddingException(
+ "Output buffer (" + outLen + ") is too small to " +
+ "hold the produced data (" + tmpBuffer.length + ")");
}
System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length);
n = tmpBuffer.length;
--- a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_util.c Wed Jul 05 22:08:15 2017 +0200
@@ -558,7 +558,7 @@
pCharArray = (*env)->GetStringUTFChars(env, jArray, &isCopy);
if (pCharArray == NULL) { return; }
- *ckpLength = strlen(pCharArray);
+ *ckpLength = (CK_ULONG) strlen(pCharArray);
*ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR));
if (*ckpArray == NULL) {
(*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
--- a/jdk/src/jdk.crypto.pkcs11/unix/native/libj2pkcs11/j2secmod_md.c Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.crypto.pkcs11/unix/native/libj2pkcs11/j2secmod_md.c Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_Secmod_nssGetLibraryHandle
(JNIEnv *env, jclass thisClass, jstring jLibName)
{
+ void *hModule;
const char *libName = (*env)->GetStringUTFChars(env, jLibName, NULL);
if (libName == NULL) {
return 0L;
@@ -56,9 +57,9 @@
// look up existing handle only, do not load
#if defined(AIX)
- void *hModule = dlopen(libName, RTLD_LAZY);
+ hModule = dlopen(libName, RTLD_LAZY);
#else
- void *hModule = dlopen(libName, RTLD_NOLOAD);
+ hModule = dlopen(libName, RTLD_NOLOAD);
#endif
dprintf2("-handle for %s: %u\n", libName, hModule);
(*env)->ReleaseStringUTFChars(env, jLibName, libName);
--- a/jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c Wed Jul 05 22:08:15 2017 +0200
@@ -31,6 +31,9 @@
#include "j2secmod.h"
+extern void throwNullPointerException(JNIEnv *env, const char *message);
+extern void throwIOException(JNIEnv *env, const char *message);
+
void *findFunction(JNIEnv *env, jlong jHandle, const char *functionName) {
HINSTANCE hModule = (HINSTANCE)jHandle;
void *fAddress = GetProcAddress(hModule, functionName);
--- a/jdk/src/jdk.internal.opt/share/classes/module-info.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.internal.opt/share/classes/module-info.java Wed Jul 05 22:08:15 2017 +0200
@@ -24,5 +24,5 @@
*/
module jdk.internal.opt {
- exports jdk.internal.joptsimple to jdk.jlink;
+ exports jdk.internal.joptsimple to jdk.jlink, jdk.jshell;
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Wed Jul 05 22:08:15 2017 +0200
@@ -78,28 +78,21 @@
private final List<String> args;
private final Set<String> modules;
- public DefaultExecutableImage(Path home, Set<String> modules) {
- this(home, modules, createArgs(home));
- }
-
- private DefaultExecutableImage(Path home, Set<String> modules,
- List<String> args) {
+ DefaultExecutableImage(Path home, Set<String> modules) {
Objects.requireNonNull(home);
- Objects.requireNonNull(args);
if (!Files.exists(home)) {
throw new IllegalArgumentException("Invalid image home");
}
this.home = home;
this.modules = Collections.unmodifiableSet(modules);
- this.args = Collections.unmodifiableList(args);
+ this.args = createArgs(home);
}
private static List<String> createArgs(Path home) {
Objects.requireNonNull(home);
- List<String> javaArgs = new ArrayList<>();
- javaArgs.add(home.resolve("bin").
- resolve(getJavaProcessName()).toString());
- return javaArgs;
+ Path binDir = home.resolve("bin");
+ String java = Files.exists(binDir.resolve("java"))? "java" : "java.exe";
+ return List.of(binDir.resolve(java).toString());
}
@Override
@@ -130,6 +123,7 @@
private final Path root;
private final Path mdir;
private final Set<String> modules = new HashSet<>();
+ private String targetOsName;
/**
* Default image builder constructor.
@@ -171,6 +165,11 @@
@Override
public void storeFiles(ResourcePool files) {
try {
+ // populate release properties up-front. targetOsName
+ // field is assigned from there and used elsewhere.
+ Properties release = releaseProperties(files);
+ Path bin = root.resolve("bin");
+
files.entries().forEach(f -> {
if (!f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
try {
@@ -186,11 +185,11 @@
modules.add(m.name());
}
});
- storeFiles(modules, releaseProperties(files));
+
+ storeFiles(modules, release);
if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) {
// launchers in the bin directory need execute permission
- Path bin = root.resolve("bin");
if (Files.isDirectory(bin)) {
Files.list(bin)
.filter(f -> !f.toString().endsWith(".diz"))
@@ -208,7 +207,11 @@
}
}
- prepareApplicationFiles(files, modules);
+ // If native files are stripped completely, <root>/bin dir won't exist!
+ // So, don't bother generating launcher scripts.
+ if (Files.isDirectory(bin)) {
+ prepareApplicationFiles(files, modules);
+ }
} catch (IOException ex) {
throw new PluginException(ex);
}
@@ -226,6 +229,11 @@
props.setProperty("JAVA_VERSION", System.getProperty("java.version"));
});
+ this.targetOsName = props.getProperty("OS_NAME");
+ if (this.targetOsName == null) {
+ throw new PluginException("TargetPlatform attribute is missing for java.base module");
+ }
+
Optional<ResourcePoolEntry> release = pool.findEntry("/java.base/release");
if (release.isPresent()) {
try (InputStream is = release.get().content()) {
@@ -373,7 +381,7 @@
Files.createLink(dstFile, target);
}
- private static String nativeDir(String filename) {
+ private String nativeDir(String filename) {
if (isWindows()) {
if (filename.endsWith(".dll") || filename.endsWith(".diz")
|| filename.endsWith(".pdb") || filename.endsWith(".map")) {
@@ -386,8 +394,8 @@
}
}
- private static boolean isWindows() {
- return System.getProperty("os.name").startsWith("Windows");
+ private boolean isWindows() {
+ return targetOsName.startsWith("Windows");
}
/**
@@ -452,12 +460,10 @@
}
}
- private static String getJavaProcessName() {
- return isWindows() ? "java.exe" : "java";
- }
-
public static ExecutableImage getExecutableImage(Path root) {
- if (Files.exists(root.resolve("bin").resolve(getJavaProcessName()))) {
+ Path binDir = root.resolve("bin");
+ if (Files.exists(binDir.resolve("java")) ||
+ Files.exists(binDir.resolve("java.exe"))) {
return new DefaultExecutableImage(root, retrieveModules(root));
}
return null;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Wed Jul 05 22:08:15 2017 +0200
@@ -172,7 +172,7 @@
private final Plugin lastSorter;
private final List<Plugin> plugins = new ArrayList<>();
private final List<ResourcePrevisitor> resourcePrevisitors = new ArrayList<>();
-
+ private final boolean validate;
public ImagePluginStack() {
this(null, Collections.emptyList(), null);
@@ -181,6 +181,13 @@
public ImagePluginStack(ImageBuilder imageBuilder,
List<Plugin> plugins,
Plugin lastSorter) {
+ this(imageBuilder, plugins, lastSorter, true);
+ }
+
+ public ImagePluginStack(ImageBuilder imageBuilder,
+ List<Plugin> plugins,
+ Plugin lastSorter,
+ boolean validate) {
this.imageBuilder = Objects.requireNonNull(imageBuilder);
this.lastSorter = lastSorter;
this.plugins.addAll(Objects.requireNonNull(plugins));
@@ -190,6 +197,7 @@
resourcePrevisitors.add((ResourcePrevisitor) p);
}
});
+ this.validate = validate;
}
public void operate(ImageProvider provider) throws Exception {
@@ -268,6 +276,7 @@
frozenOrder = ((OrderedResourcePoolManager.OrderedResourcePool)resPool).getOrderedList();
}
}
+
return resPool;
}
@@ -458,7 +467,11 @@
throws Exception {
Objects.requireNonNull(original);
Objects.requireNonNull(transformed);
- imageBuilder.storeFiles(new LastPoolManager(transformed).resourcePool());
+ ResourcePool lastPool = new LastPoolManager(transformed).resourcePool();
+ if (validate) {
+ ResourcePoolConfiguration.validate(lastPool);
+ }
+ imageBuilder.storeFiles(lastPool);
}
public ExecutableImage getExecutableImage() throws IOException {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java Wed Jul 05 22:08:15 2017 +0200
@@ -5,7 +5,7 @@
* 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 "Classfile" exception as provided
+ * 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
+
+final class ResourcePoolConfiguration {
+ private ResourcePoolConfiguration() {}
+
+ private static ModuleDescriptor descriptorOf(ResourcePoolModule mod) {
+ ModuleDescriptor md = mod.descriptor();
+
+ // drop hashes
+ ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name());
+ md.requires().stream()
+ .forEach(builder::requires);
+ md.exports().stream()
+ .forEach(builder::exports);
+ md.uses().stream()
+ .forEach(builder::uses);
+ md.provides().values().stream()
+ .forEach(builder::provides);
+
+ // build the proper concealed packages
+ Set<String> exps = md.exports().stream()
+ .map(ModuleDescriptor.Exports::source)
+ .collect(Collectors.toSet());
+
+ mod.packages().stream()
+ .filter(pn -> !exps.contains(pn))
+ .forEach(builder::conceals);
+
+ md.version().ifPresent(builder::version);
+ md.mainClass().ifPresent(builder::mainClass);
+ md.osName().ifPresent(builder::osName);
+ md.osArch().ifPresent(builder::osArch);
+ md.osVersion().ifPresent(builder::osVersion);
+
+ return builder.build();
+ }
+
+ private static ModuleReference moduleReference(ModuleDescriptor desc) {
+ return new ModuleReference(desc, null, () -> {
+ IOException ioe = new IOException("<module reader unsupported>");
+ throw new UncheckedIOException(ioe);
+ });
+ }
+
+ private static Map<String, ModuleReference> allModRefs(ResourcePool pool) {
+ return pool.moduleView().modules().
+ collect(Collectors.toMap(ResourcePoolModule::name,
+ m -> moduleReference(descriptorOf(m))));
+ }
+
+ private static void checkPackages(ResourcePool pool) {
+ // check that each resource pool module's packages()
+ // returns a set that is consistent with the module
+ // descriptor of that module.
+
+ pool.moduleView().modules().forEach(m -> {
+ ModuleDescriptor desc = m.descriptor();
+ if (!desc.packages().equals(m.packages())) {
+ throw new RuntimeException("Module " + m.name() +
+ "'s descriptor returns inconsistent package set");
+ }
+ });
+ }
+
+ static Configuration validate(ResourcePool pool) {
+ checkPackages(pool);
+ final Map<String, ModuleReference> nameToModRef = allModRefs(pool);
+ final Set<ModuleReference> allRefs = new HashSet<>(nameToModRef.values());
+
+ final ModuleFinder finder = new ModuleFinder() {
+ @Override
+ public Optional<ModuleReference> find(String name) {
+ return Optional.ofNullable(nameToModRef.get(name));
+ }
+
+ @Override
+ public Set<ModuleReference> findAll() {
+ return allRefs;
+ }
+ };
+
+ return Configuration.empty().resolveRequires(
+ finder, ModuleFinder.of(), nameToModRef.keySet());
+ }
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java Wed Jul 05 22:08:15 2017 +0200
@@ -24,7 +24,11 @@
*/
package jdk.tools.jlink.internal.plugins;
+import java.io.File;
+import java.io.IOException;
import java.lang.invoke.MethodType;
+import java.nio.file.Files;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
@@ -32,6 +36,7 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaLangInvokeAccess;
import jdk.tools.jlink.plugin.ResourcePoolEntry;
@@ -47,15 +52,9 @@
private static final String NAME = "generate-jli-classes";
- private static final String BMH_PARAM = "bmh";
-
- private static final String BMH_SPECIES_PARAM = "bmh-species";
-
- private static final String DMH_PARAM = "dmh";
-
private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
- private static final String DIRECT_METHOD_HANDLE = "java/lang/invoke/DirectMethodHandle$Holder";
+ private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder";
private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual";
private static final String DMH_INVOKE_STATIC = "invokeStatic";
private static final String DMH_INVOKE_SPECIAL = "invokeSpecial";
@@ -63,15 +62,17 @@
private static final String DMH_INVOKE_INTERFACE = "invokeInterface";
private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit";
- private static final String DELEGATING_METHOD_HANDLE = "java/lang/invoke/DelegatingMethodHandle$Holder";
-
- private static final String BASIC_FORMS_HANDLE = "java/lang/invoke/LambdaForm$Holder";
+ private static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder";
+ private static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder";
+ private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder";
private static final JavaLangInvokeAccess JLIA
= SharedSecrets.getJavaLangInvokeAccess();
List<String> speciesTypes;
+ List<String> invokerTypes;
+
Map<String, List<String>> dmhMethods;
public GenerateJLIClassesPlugin() {
@@ -117,21 +118,29 @@
}
/**
+ * @return the default invoker forms to generate.
+ */
+ private static List<String> defaultInvokers() {
+ return List.of("LL_L", "LL_I", "LILL_I", "L6_L");
+ }
+
+ /**
* @return the list of default DirectMethodHandle methods to generate.
*/
- public static Map<String, List<String>> defaultDMHMethods() {
+ private static Map<String, List<String>> defaultDMHMethods() {
return Map.of(
- DMH_INVOKE_VIRTUAL, List.of("_L", "L_L", "LI_I", "LL_V"),
- DMH_INVOKE_SPECIAL, List.of("L_I", "L_L", "LF_L", "LD_L", "LL_L",
- "L3_L", "L4_L", "L5_L", "L6_L", "L7_L", "LI_I", "LI_L", "LIL_I",
- "LII_I", "LII_L", "LLI_L", "LLI_I", "LILI_I", "LIIL_L",
- "LIILL_L", "LIILL_I", "LIIL_I", "LILIL_I", "LILILL_I",
- "LILII_I", "LI3_I", "LI3L_I", "LI3LL_I", "LI3_L", "LI4_I"),
- DMH_INVOKE_STATIC, List.of("II_I", "IL_I", "ILIL_I", "ILII_I",
- "_I", "_L", "_V", "D_L", "F_L", "I_I", "II_L", "LI_L",
- "L_V", "L_L", "LL_L", "L3_L", "L4_L", "L5_L", "L6_L",
- "L7_L", "L8_L", "L9_L", "L9I_L", "L9II_L", "L9IIL_L",
- "L10_L", "L11_L", "L12_L", "L13_L", "L13I_L", "L13II_L")
+ DMH_INVOKE_VIRTUAL, List.of("L_L", "LL_L", "LLI_I", "L3_V"),
+ DMH_INVOKE_SPECIAL, List.of("LL_I", "LL_L", "LLF_L", "LLD_L", "L3_L",
+ "L4_L", "L5_L", "L6_L", "L7_L", "L8_L", "LLI_I", "LLI_L",
+ "LLIL_I", "LLII_I", "LLII_L", "L3I_L", "L3I_I", "LLILI_I",
+ "LLIIL_L", "LLIILL_L", "LLIILL_I", "LLIIL_I", "LLILIL_I",
+ "LLILILL_I", "LLILII_I", "LLI3_I", "LLI3L_I", "LLI3LL_I",
+ "LLI3_L", "LLI4_I"),
+ DMH_INVOKE_STATIC, List.of("LII_I", "LIL_I", "LILIL_I", "LILII_I",
+ "L_I", "L_L", "L_V", "LD_L", "LF_L", "LI_I", "LII_L", "LLI_L",
+ "LL_V", "LL_L", "L3_L", "L4_L", "L5_L", "L6_L", "L7_L",
+ "L8_L", "L9_L", "L10_L", "L10I_L", "L10II_L", "L10IIL_L",
+ "L11_L", "L12_L", "L13_L", "L14_L", "L14I_L", "L14II_L")
);
}
@@ -150,72 +159,91 @@
public void configure(Map<String, String> config) {
String mainArgument = config.get(NAME);
- // Enable by default
- boolean bmhEnabled = true;
- boolean dmhEnabled = true;
- if (mainArgument != null) {
- List<String> args = Arrays.asList(mainArgument.split(","));
- if (!args.contains(BMH_PARAM)) {
- bmhEnabled = false;
- }
- if (!args.contains(DMH_PARAM)) {
- dmhEnabled = false;
- }
- }
+ if (mainArgument != null && mainArgument.startsWith("@")) {
+ File file = new File(mainArgument.substring(1));
+ if (file.exists()) {
+ speciesTypes = new ArrayList<>();
+ invokerTypes = new ArrayList<>();
+ dmhMethods = new HashMap<>();
+ Stream<String> lines = fileLines(file);
- if (!bmhEnabled) {
- speciesTypes = List.of();
+ lines.map(line -> line.split(" "))
+ .forEach(parts -> {
+ switch (parts[0]) {
+ case "[BMH_RESOLVE]":
+ speciesTypes.add(expandSignature(parts[1]));
+ break;
+ case "[LF_RESOLVE]":
+ String methodType = parts[3];
+ validateMethodType(methodType);
+ if (parts[1].contains("Invokers")) {
+ invokerTypes.add(methodType);
+ } else if (parts[1].contains("DirectMethodHandle")) {
+ String dmh = parts[2];
+ // ignore getObject etc for now (generated
+ // by default)
+ if (DMH_METHOD_TYPE_MAP.containsKey(dmh)) {
+ addDMHMethodType(dmh, methodType);
+ }
+ }
+ break;
+ default: break; // ignore
+ }
+ });
+ }
} else {
- String args = config.get(BMH_SPECIES_PARAM);
- List<String> bmhSpecies;
- if (args != null && !args.isEmpty()) {
- bmhSpecies = Arrays.stream(args.split(","))
- .map(String::trim)
- .filter(s -> !s.isEmpty())
- .collect(Collectors.toList());
- } else {
- bmhSpecies = defaultSpecies();
- }
-
+ List<String> bmhSpecies = defaultSpecies();
// Expand BMH species signatures
speciesTypes = bmhSpecies.stream()
.map(type -> expandSignature(type))
.collect(Collectors.toList());
- }
+
+ invokerTypes = defaultInvokers();
+ validateMethodTypes(invokerTypes);
- // DirectMethodHandles
- if (!dmhEnabled) {
- dmhMethods = Map.of();
- } else {
- dmhMethods = new HashMap<>();
- for (String dmhParam : DMH_METHOD_TYPE_MAP.keySet()) {
- String args = config.get(dmhParam);
- if (args != null && !args.isEmpty()) {
- List<String> dmhMethodTypes = Arrays.stream(args.split(","))
- .map(String::trim)
- .filter(s -> !s.isEmpty())
- .collect(Collectors.toList());
- dmhMethods.put(dmhParam, dmhMethodTypes);
- // Validation check
- for (String type : dmhMethodTypes) {
- String[] typeParts = type.split("_");
- // check return type (second part)
- if (typeParts.length != 2 || typeParts[1].length() != 1
- || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) {
- throw new PluginException(
- "Method type signature must be of form [LJIFD]*_[LJIFDV]");
- }
- // expand and check arguments (first part)
- expandSignature(typeParts[0]);
- }
- }
- }
- if (dmhMethods.isEmpty()) {
- dmhMethods = defaultDMHMethods();
+ dmhMethods = defaultDMHMethods();
+ for (List<String> dmhMethodTypes : dmhMethods.values()) {
+ validateMethodTypes(dmhMethodTypes);
}
}
}
+ private void addDMHMethodType(String dmh, String methodType) {
+ validateMethodType(methodType);
+ List<String> methodTypes = dmhMethods.get(dmh);
+ if (methodTypes == null) {
+ methodTypes = new ArrayList<>();
+ dmhMethods.put(dmh, methodTypes);
+ }
+ methodTypes.add(methodType);
+ }
+
+ private Stream<String> fileLines(File file) {
+ try {
+ return Files.lines(file.toPath());
+ } catch (IOException io) {
+ throw new PluginException("Couldn't read file");
+ }
+ }
+
+ private void validateMethodTypes(List<String> dmhMethodTypes) {
+ for (String type : dmhMethodTypes) {
+ validateMethodType(type);
+ }
+ }
+
+ private void validateMethodType(String type) {
+ String[] typeParts = type.split("_");
+ // check return type (second part)
+ if (typeParts.length != 2 || typeParts[1].length() != 1
+ || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) {
+ throw new PluginException(
+ "Method type signature must be of form [LJIFD]*_[LJIFDV]");
+ }
+ // expand and check arguments (first part)
+ expandSignature(typeParts[0]);
+ }
+
private static void requireBasicType(char c) {
if ("LIJFD".indexOf(c) < 0) {
throw new PluginException(
@@ -228,9 +256,10 @@
// Copy all but DMH_ENTRY to out
in.transformAndCopy(entry -> {
// filter out placeholder entries
- if (entry.path().equals(DIRECT_METHOD_HANDLE_ENTRY) ||
- entry.path().equals(DELEGATING_METHOD_HANDLE_ENTRY) ||
- entry.path().equals(BASIC_FORMS_HANDLE_ENTRY)) {
+ if (entry.path().equals(DIRECT_METHOD_HOLDER_ENTRY) ||
+ entry.path().equals(DELEGATING_METHOD_HOLDER_ENTRY) ||
+ entry.path().equals(INVOKERS_HOLDER_ENTRY) ||
+ entry.path().equals(BASIC_FORMS_HOLDER_ENTRY)) {
return null;
} else {
return entry;
@@ -265,42 +294,72 @@
for (List<String> entry : dmhMethods.values()) {
count += entry.size();
}
- MethodType[] methodTypes = new MethodType[count];
+ MethodType[] directMethodTypes = new MethodType[count];
int[] dmhTypes = new int[count];
int index = 0;
for (Map.Entry<String, List<String>> entry : dmhMethods.entrySet()) {
String dmhType = entry.getKey();
for (String type : entry.getValue()) {
- methodTypes[index] = asMethodType(type);
+ // The DMH type to actually ask for is retrieved by removing
+ // the first argument, which needs to be of Object.class
+ MethodType mt = asMethodType(type);
+ if (mt.parameterCount() < 1 ||
+ mt.parameterType(0) != Object.class) {
+ throw new PluginException(
+ "DMH type parameter must start with L");
+ }
+ directMethodTypes[index] = mt.dropParameterTypes(0, 1);
dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
index++;
}
}
+ MethodType[] invokerMethodTypes = new MethodType[this.invokerTypes.size()];
+ for (int i = 0; i < invokerTypes.size(); i++) {
+ // The invoker type to ask for is retrieved by removing the first
+ // and the last argument, which needs to be of Object.class
+ MethodType mt = asMethodType(invokerTypes.get(i));
+ final int lastParam = mt.parameterCount() - 1;
+ if (mt.parameterCount() < 2 ||
+ mt.parameterType(0) != Object.class ||
+ mt.parameterType(lastParam) != Object.class) {
+ throw new PluginException(
+ "Invoker type parameter must start and end with L");
+ }
+ mt = mt.dropParameterTypes(lastParam, lastParam + 1);
+ invokerMethodTypes[i] = mt.dropParameterTypes(0, 1);
+ }
try {
byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes(
- DIRECT_METHOD_HANDLE, methodTypes, dmhTypes);
+ DIRECT_HOLDER, directMethodTypes, dmhTypes);
ResourcePoolEntry ndata = ResourcePoolEntry
- .create(DIRECT_METHOD_HANDLE_ENTRY, bytes);
+ .create(DIRECT_METHOD_HOLDER_ENTRY, bytes);
out.add(ndata);
bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes(
- DELEGATING_METHOD_HANDLE, methodTypes);
- ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HANDLE_ENTRY, bytes);
+ DELEGATING_HOLDER, directMethodTypes);
+ ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HOLDER_ENTRY, bytes);
out.add(ndata);
- bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HANDLE);
- ndata = ResourcePoolEntry.create(BASIC_FORMS_HANDLE_ENTRY, bytes);
+ bytes = JLIA.generateInvokersHolderClassBytes(INVOKERS_HOLDER,
+ invokerMethodTypes);
+ ndata = ResourcePoolEntry.create(INVOKERS_HOLDER_ENTRY, bytes);
+ out.add(ndata);
+
+ bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HOLDER);
+ ndata = ResourcePoolEntry.create(BASIC_FORMS_HOLDER_ENTRY, bytes);
out.add(ndata);
} catch (Exception ex) {
throw new PluginException(ex);
}
}
- private static final String DIRECT_METHOD_HANDLE_ENTRY =
- "/java.base/" + DIRECT_METHOD_HANDLE + ".class";
- private static final String DELEGATING_METHOD_HANDLE_ENTRY =
- "/java.base/" + DELEGATING_METHOD_HANDLE + ".class";
- private static final String BASIC_FORMS_HANDLE_ENTRY =
- "/java.base/" + BASIC_FORMS_HANDLE + ".class";
+ private static final String DIRECT_METHOD_HOLDER_ENTRY =
+ "/java.base/" + DIRECT_HOLDER + ".class";
+ private static final String DELEGATING_METHOD_HOLDER_ENTRY =
+ "/java.base/" + DELEGATING_HOLDER + ".class";
+ private static final String BASIC_FORMS_HOLDER_ENTRY =
+ "/java.base/" + BASIC_FORMS_HOLDER + ".class";
+ private static final String INVOKERS_HOLDER_ENTRY =
+ "/java.base/" + INVOKERS_HOLDER + ".class";
// Convert LL -> LL, L3 -> LLL
private static String expandSignature(String signature) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Wed Jul 05 22:08:15 2017 +0200
@@ -56,7 +56,7 @@
copy-files.description=\
If files to copy are not absolute path, JDK home dir is used.\n\
-e.g.: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewehere/conf.txt
+e.g.: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewhere/conf.txt
exclude-files.argument=<pattern-list> of files to exclude
@@ -68,10 +68,12 @@
exclude-resources.description=\
Specify resources to exclude. e.g.: **.jcov,glob:**/META-INF/**
-generate-jli-classes.argument=<bmh[:bmh-species=LL,L3,...]>
+generate-jli-classes.argument=<@filename>
generate-jli-classes.description=\
-Concrete java.lang.invoke classes to generate
+Takes a file hinting to jlink what java.lang.invoke classes to pre-generate. If\n\
+this flag is not specified a default set of classes will be generated, so to \n\
+disable pre-generation supply the name of an empty or non-existing file
installed-modules.description=Fast loading of module descriptors (always enabled)
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Wed Jul 05 22:08:15 2017 +0200
@@ -165,8 +165,8 @@
walk(inode.child, process);
} else {
process.accept(inode);
- walk(inode.sibling, process);
}
+ walk(inode.sibling, process);
}
/**
--- a/jdk/test/ProblemList.txt Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/ProblemList.txt Wed Jul 05 22:08:15 2017 +0200
@@ -124,10 +124,6 @@
# jdk_lang
java/lang/StringCoding/CheckEncodings.sh 7008363 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java 8160690 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java 8160690 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java 8160690 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java 8160690 generic-all
############################################################################
@@ -211,8 +207,6 @@
java/rmi/transport/dgcDeadLock/DGCDeadLock.java 8029360 macosx-all
-sun/rmi/runtime/Log/6409194/NoConsoleOutput.java 8164124 windows-all
-
############################################################################
# jdk_security
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Wed Jul 05 22:08:15 2017 +0200
@@ -205,12 +205,13 @@
.replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/")
.replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run")
.replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke")
- // DMHs may or may not be pre-generated, making frames differ
+ // LFs may or may not be pre-generated, making frames differ
.replaceAll("DirectMethodHandle\\$Holder", "LambdaForm\\$DMH")
- .replaceAll("DMH\\.invoke", "DMH/xxxxxxxx.invoke")
+ .replaceAll("Invokers\\$Holder", "LambdaForm\\$MH")
+ .replaceAll("MH\\.invoke", "MH/xxxxxxxx.invoke")
// invoke frames may or may not have basic method type
// information encoded for diagnostic purposes
- .replaceAll("xx\\.invoke([A-Za-z]*)_[A-Z]+_[A-Z]", "xx.invoke$1")
+ .replaceAll("xx\\.invoke([A-Za-z]*)_[A-Z_]+", "xx.invoke$1")
.replaceAll("\\$[0-9]+", "\\$??");
} else {
return produced;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/HttpCookie/CookieNegativeMaxAge.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8005068
+ * @summary Check that any negative maxAge is treated as "unspecified" and
+ * if header contains cookie with "expires" attribute in the past then cookie
+ * is created with maxAge=0 meaning it is specified to be immediately expired.
+ * @run main CookieNegativeMaxAge
+ */
+
+
+import java.net.HttpCookie;
+import java.util.List;
+
+public class CookieNegativeMaxAge {
+
+ public static void main(String... args) {
+ HttpCookie cookie = new HttpCookie("testCookie", "value");
+ cookie.setMaxAge(Integer.MIN_VALUE);
+ if (cookie.hasExpired()) {
+ throw new RuntimeException("Cookie has unexpectedly expired");
+ }
+
+ List<HttpCookie> cookies = HttpCookie.parse("Set-Cookie: " +
+ "expiredCookie=value; expires=Thu, 01 Jan 1970 00:00:00 GMT");
+ if (cookies.size() == 1) {
+ if (cookies.get(0).getMaxAge() != 0) {
+ throw new RuntimeException("Cookie maxAge expected to be 0");
+ }
+ } else {
+ throw new RuntimeException("Header was incorrectly parsed");
+ }
+ }
+}
--- a/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,6 +68,7 @@
MulticastSocket msock = null;
List<SocketAddress> failedGroups = new ArrayList<SocketAddress>();
+ Sender sender = null;
try {
msock = new MulticastSocket();
int port = msock.getLocalPort();
@@ -80,9 +81,8 @@
groups.add(new InetSocketAddress(InetAddress.getByName("::ffff:224.1.1.2"), port));
groups.add(new InetSocketAddress(InetAddress.getByName("ff02::1:1"), port));
- Thread sender = new Thread(new Sender(groups));
- sender.setDaemon(true); // we want sender to stop when main thread exits
- sender.start();
+ sender = new Sender(groups);
+ new Thread(sender).start();
// Now try to receive multicast packets. we should not see any of them
// since we disable loopback mode.
@@ -107,6 +107,9 @@
}
} finally {
if (msock != null) try { msock.close(); } catch (Exception e) {}
+ if (sender != null) {
+ sender.stop();
+ }
}
if (failedGroups.size() > 0) {
@@ -119,6 +122,7 @@
static class Sender implements Runnable {
private List<SocketAddress> sendToGroups;
+ private volatile boolean stop;
public Sender(List<SocketAddress> groups) {
sendToGroups = groups;
@@ -136,7 +140,7 @@
MulticastSocket msock = new MulticastSocket();
msock.setLoopbackMode(true); // disable loopback mode
- for (;;) {
+ while (!stop) {
for (DatagramPacket packet : packets) {
msock.send(packet);
}
@@ -147,5 +151,9 @@
throw new RuntimeException(e);
}
}
+
+ void stop() {
+ stop = true;
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/ProxyAuthTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+/*
+ * @test
+ * @bug 8163561
+ * @modules java.base/sun.net.www
+ * @summary Verify that Proxy-Authenticate header is correctly handled
+ *
+ * @run main/othervm ProxyAuthTest
+ */
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.Authenticator;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpResponse;
+import java.util.Base64;
+
+import sun.net.www.MessageHeader;
+
+public class ProxyAuthTest {
+ private static final String AUTH_USER = "user";
+ private static final String AUTH_PASSWORD = "password";
+
+ public static void main(String[] args) throws Exception {
+ try (ServerSocket ss = new ServerSocket(0)) {
+ int port = ss.getLocalPort();
+ MyProxy proxy = new MyProxy(ss);
+ (new Thread(proxy)).start();
+ System.out.println("Proxy listening port " + port);
+
+ Auth auth = new Auth();
+ InetSocketAddress paddr = new InetSocketAddress("localhost", port);
+
+ URI uri = new URI("http://www.google.ie/");
+ HttpClient client = HttpClient.create()
+ .proxy(ProxySelector.of(paddr))
+ .authenticator(auth)
+ .build();
+ HttpResponse resp = client.request(uri)
+ .GET()
+ .responseAsync()
+ .get();
+ if (resp.statusCode() != 404) {
+ throw new RuntimeException("Unexpected status code: " + resp.statusCode());
+ }
+
+ if (auth.isCalled) {
+ System.out.println("Authenticator is called");
+ } else {
+ throw new RuntimeException("Authenticator is not called");
+ }
+
+ if (!proxy.matched) {
+ throw new RuntimeException("Proxy authentication failed");
+ }
+ }
+ }
+
+ static class Auth extends Authenticator {
+ private volatile boolean isCalled;
+
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ System.out.println("scheme: " + this.getRequestingScheme());
+ isCalled = true;
+ return new PasswordAuthentication(AUTH_USER,
+ AUTH_PASSWORD.toCharArray());
+ }
+ }
+
+ static class MyProxy implements Runnable {
+ final ServerSocket ss;
+ private volatile boolean matched;
+
+ MyProxy(ServerSocket ss) {
+ this.ss = ss;
+ }
+
+ public void run() {
+ for (int i = 0; i < 2; i++) {
+ try (Socket s = ss.accept();
+ InputStream in = s.getInputStream();
+ OutputStream os = s.getOutputStream();
+ BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(os));
+ PrintWriter out = new PrintWriter(writer);) {
+ MessageHeader headers = new MessageHeader(in);
+ System.out.println("Proxy: received " + headers);
+
+ String authInfo = headers
+ .findValue("Proxy-Authorization");
+ if (authInfo != null) {
+ authenticate(authInfo);
+ out.print("HTTP/1.1 404 Not found\r\n");
+ out.print("\r\n");
+ System.out.println("Proxy: 404");
+ out.flush();
+ } else {
+ out.print("HTTP/1.1 407 Proxy Authorization Required\r\n");
+ out.print(
+ "Proxy-Authenticate: Basic realm=\"a fake realm\"\r\n");
+ out.print("\r\n");
+ System.out.println("Proxy: Authorization required");
+ out.flush();
+ }
+ } catch (IOException x) {
+ System.err.println("Unexpected IOException from proxy.");
+ x.printStackTrace();
+ break;
+ }
+ }
+ }
+
+ private void authenticate(String authInfo) throws IOException {
+ try {
+ authInfo.trim();
+ int ind = authInfo.indexOf(' ');
+ String recvdUserPlusPass = authInfo.substring(ind + 1).trim();
+ // extract encoded username:passwd
+ String value = new String(
+ Base64.getMimeDecoder().decode(recvdUserPlusPass));
+ String userPlusPassword = AUTH_USER + ":" + AUTH_PASSWORD;
+ if (userPlusPassword.equals(value)) {
+ matched = true;
+ System.out.println("Proxy: client authentication successful");
+ } else {
+ System.err.println(
+ "Proxy: client authentication failed, expected ["
+ + userPlusPassword + "], actual [" + value
+ + "]");
+ }
+ } catch (Exception e) {
+ throw new IOException(
+ "Proxy received invalid Proxy-Authorization value: "
+ + authInfo);
+ }
+ }
+ }
+
+}
+
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -119,19 +119,31 @@
ExecutorService pool = Executors.newCachedThreadPool();
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withCachedThreadPool(pool, rand.nextInt(10));
- testShutdownWithChannels(pool, group);
+ try {
+ testShutdownWithChannels(pool, group);
+ } finally {
+ group.shutdown();
+ }
}
for (int i = 0; i < 100; i++) {
int nThreads = 1 + rand.nextInt(8);
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withFixedThreadPool(nThreads, threadFactory);
- testShutdownWithChannels(null, group);
+ try {
+ testShutdownWithChannels(null, group);
+ } finally {
+ group.shutdown();
+ }
}
for (int i = 0; i < 100; i++) {
ExecutorService pool = Executors.newCachedThreadPool();
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withThreadPool(pool);
- testShutdownWithChannels(pool, group);
+ try {
+ testShutdownWithChannels(pool, group);
+ } finally {
+ group.shutdown();
+ }
}
}
@@ -164,19 +176,31 @@
ExecutorService pool = pool = Executors.newCachedThreadPool();
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withCachedThreadPool(pool, rand.nextInt(5));
- testShutdownNow(pool, group);
+ try {
+ testShutdownNow(pool, group);
+ } finally {
+ group.shutdown();
+ }
}
for (int i = 0; i < 10; i++) {
int nThreads = 1 + rand.nextInt(8);
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withFixedThreadPool(nThreads, threadFactory);
- testShutdownNow(null, group);
+ try {
+ testShutdownNow(null, group);
+ } finally {
+ group.shutdown();
+ }
}
for (int i = 0; i < 10; i++) {
ExecutorService pool = Executors.newCachedThreadPool();
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withThreadPool(pool);
- testShutdownNow(pool, group);
+ try {
+ testShutdownNow(pool, group);
+ } finally {
+ group.shutdown();
+ }
}
}
@@ -186,78 +210,78 @@
AsynchronousChannelGroup group =
AsynchronousChannelGroup.withFixedThreadPool(1, threadFactory);
- AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
- AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(group);
+ try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+ AsynchronousServerSocketChannel listener =
+ AsynchronousServerSocketChannel.open(group)) {
- // initiate accept
- listener.bind(new InetSocketAddress(0));
- Future<AsynchronousSocketChannel> result = listener.accept();
-
- // shutdown group
- group.shutdown();
- if (!group.isShutdown())
- throw new RuntimeException("Group should be shutdown");
+ // initiate accept
+ listener.bind(new InetSocketAddress(0));
+ Future<AsynchronousSocketChannel> result = listener.accept();
- // attempt to create another channel
- try {
- AsynchronousSocketChannel.open(group);
- throw new RuntimeException("ShutdownChannelGroupException expected");
- } catch (ShutdownChannelGroupException x) {
- }
- try {
- AsynchronousServerSocketChannel.open(group);
- throw new RuntimeException("ShutdownChannelGroupException expected");
- } catch (ShutdownChannelGroupException x) {
- }
+ // shutdown group
+ group.shutdown();
+ if (!group.isShutdown())
+ throw new RuntimeException("Group should be shutdown");
+
+ // attempt to create another channel
+ try {
+ AsynchronousSocketChannel.open(group);
+ throw new RuntimeException("ShutdownChannelGroupException expected");
+ } catch (ShutdownChannelGroupException x) {
+ }
+ try {
+ AsynchronousServerSocketChannel.open(group);
+ throw new RuntimeException("ShutdownChannelGroupException expected");
+ } catch (ShutdownChannelGroupException x) {
+ }
- // attempt to create another channel by connecting. This should cause
- // the accept operation to fail.
- InetAddress lh = InetAddress.getLocalHost();
- int port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
- InetSocketAddress isa = new InetSocketAddress(lh, port);
- ch.connect(isa).get();
- try {
- result.get();
- throw new RuntimeException("Connection was accepted");
- } catch (ExecutionException x) {
- Throwable cause = x.getCause();
- if (!(cause instanceof IOException))
- throw new RuntimeException("Cause should be IOException");
- cause = cause.getCause();
- if (!(cause instanceof ShutdownChannelGroupException))
- throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
- }
+ // attempt to create another channel by connecting. This should cause
+ // the accept operation to fail.
+ InetAddress lh = InetAddress.getLocalHost();
+ int port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
+ InetSocketAddress isa = new InetSocketAddress(lh, port);
+ ch.connect(isa).get();
+ try {
+ result.get();
+ throw new RuntimeException("Connection was accepted");
+ } catch (ExecutionException x) {
+ Throwable cause = x.getCause();
+ if (!(cause instanceof IOException))
+ throw new RuntimeException("Cause should be IOException");
+ cause = cause.getCause();
+ if (!(cause instanceof ShutdownChannelGroupException))
+ throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
+ }
- // initiate another accept even though channel group is shutdown.
- Future<AsynchronousSocketChannel> res = listener.accept();
- try {
- res.get(3, TimeUnit.SECONDS);
- throw new RuntimeException("TimeoutException expected");
- } catch (TimeoutException x) {
+ // initiate another accept even though channel group is shutdown.
+ Future<AsynchronousSocketChannel> res = listener.accept();
+ try {
+ res.get(3, TimeUnit.SECONDS);
+ throw new RuntimeException("TimeoutException expected");
+ } catch (TimeoutException x) {
+ }
+ // connect to the listener which should cause the accept to complete
+ AsynchronousSocketChannel.open().connect(isa);
+ try {
+ res.get();
+ throw new RuntimeException("Connection was accepted");
+ } catch (ExecutionException x) {
+ Throwable cause = x.getCause();
+ if (!(cause instanceof IOException))
+ throw new RuntimeException("Cause should be IOException");
+ cause = cause.getCause();
+ if (!(cause instanceof ShutdownChannelGroupException))
+ throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
+ }
+
+ // group should *not* terminate as channels are open
+ boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+ if (terminated) {
+ throw new RuntimeException("Group should not have terminated");
+ }
+ } finally {
+ group.shutdown();
}
- // connect to the listener which should cause the accept to complete
- AsynchronousSocketChannel.open().connect(isa);
- try {
- res.get();
- throw new RuntimeException("Connection was accepted");
- } catch (ExecutionException x) {
- Throwable cause = x.getCause();
- if (!(cause instanceof IOException))
- throw new RuntimeException("Cause should be IOException");
- cause = cause.getCause();
- if (!(cause instanceof ShutdownChannelGroupException))
- throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
- }
-
- // group should *not* terminate as channels are open
- boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
- if (terminated)
- throw new RuntimeException("Group should not have terminated");
-
- // close channel; group should terminate quickly
- ch.close();
- listener.close();
- awaitTermination(group);
}
static void miscTests() throws Exception {
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,34 +41,36 @@
public class GroupOfOne {
public static void main(String[] args) throws Exception {
+ final List<AsynchronousSocketChannel> accepted = new ArrayList<>();
+
// create listener to accept connections
- final AsynchronousServerSocketChannel listener =
- AsynchronousServerSocketChannel.open()
- .bind(new InetSocketAddress(0));
- final List<AsynchronousSocketChannel> accepted = new ArrayList<AsynchronousSocketChannel>();
- listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
- public void completed(AsynchronousSocketChannel ch, Void att) {
- synchronized (accepted) {
- accepted.add(ch);
+ try (final AsynchronousServerSocketChannel listener =
+ AsynchronousServerSocketChannel.open()) {
+
+ listener.bind(new InetSocketAddress(0));
+ listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+ public void completed(AsynchronousSocketChannel ch, Void att) {
+ synchronized (accepted) {
+ accepted.add(ch);
+ }
+ listener.accept((Void)null, this);
}
- listener.accept((Void)null, this);
- }
- public void failed(Throwable exc, Void att) {
- }
- });
+ public void failed(Throwable exc, Void att) {
+ }
+ });
- int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
- SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
+ int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+ SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
- test(sa, true, false);
- test(sa, false, true);
- test(sa, true, true);
-
- // clean-up
- listener.close();
- synchronized (accepted) {
- for (AsynchronousSocketChannel ch: accepted) {
- ch.close();
+ test(sa, true, false);
+ test(sa, false, true);
+ test(sa, true, true);
+ } finally {
+ // clean-up
+ synchronized (accepted) {
+ for (AsynchronousSocketChannel ch: accepted) {
+ ch.close();
+ }
}
}
}
@@ -86,60 +88,60 @@
return new Thread(r);
}});
final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+ try {
+ // the latch counts down when:
+ // 1. The read operation fails (expected)
+ // 2. the close/shutdown completes
+ final CountDownLatch latch = new CountDownLatch(2);
- // the latch counts down when:
- // 1. The read operation fails (expected)
- // 2. the close/shutdown completes
- final CountDownLatch latch = new CountDownLatch(2);
+ ch.connect(sa, (Void)null, new CompletionHandler<Void,Void>() {
+ public void completed(Void result, Void att) {
+ System.out.println("Connected");
- ch.connect(sa, (Void)null, new CompletionHandler<Void,Void>() {
- public void completed(Void result, Void att) {
- System.out.println("Connected");
+ // initiate I/O operation that does not complete (successfully)
+ ByteBuffer buf = ByteBuffer.allocate(100);
+ ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() {
+ public void completed(Integer bytesRead, Void att) {
+ throw new RuntimeException();
+ }
+ public void failed(Throwable exc, Void att) {
+ if (!(exc instanceof AsynchronousCloseException))
+ throw new RuntimeException(exc);
+ System.out.println("Read failed (expected)");
+ latch.countDown();
+ }
+ });
- // initiate I/O operation that does not complete (successfully)
- ByteBuffer buf = ByteBuffer.allocate(100);
- ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() {
- public void completed(Integer bytesRead, Void att) {
+ // close channel or shutdown group
+ try {
+ if (closeChannel) {
+ System.out.print("Close channel ...");
+ ch.close();
+ System.out.println(" done.");
+ }
+ if (shutdownGroup) {
+ System.out.print("Shutdown group ...");
+ group.shutdownNow();
+ System.out.println(" done.");
+ }
+ latch.countDown();
+ } catch (IOException e) {
throw new RuntimeException();
}
- public void failed(Throwable exc, Void att) {
- if (!(exc instanceof AsynchronousCloseException))
- throw new RuntimeException(exc);
- System.out.println("Read failed (expected)");
- latch.countDown();
- }
- });
+ }
+ public void failed(Throwable exc, Void att) {
+ throw new RuntimeException(exc);
+ }
+ });
- // close channel or shutdown group
- try {
- if (closeChannel) {
- System.out.print("Close channel ...");
- ch.close();
- System.out.println(" done.");
- }
- if (shutdownGroup) {
- System.out.print("Shutdown group ...");
- group.shutdownNow();
- System.out.println(" done.");
- }
- latch.countDown();
- } catch (IOException e) {
- throw new RuntimeException();
- }
- }
- public void failed(Throwable exc, Void att) {
- throw new RuntimeException(exc);
- }
- });
-
- latch.await();
-
- // clean-up
- group.shutdown();
- boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
- if (!terminated)
- throw new RuntimeException("Group did not terminate");
-
+ latch.await();
+ } finally {
+ // clean-up
+ group.shutdown();
+ boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
+ if (!terminated)
+ throw new RuntimeException("Group did not terminate");
+ }
System.out.println("TEST OKAY");
}
}
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,89 +76,91 @@
}
public static void main(String[] args) throws Exception {
- // create listener to accept connections
- final AsynchronousServerSocketChannel listener =
- AsynchronousServerSocketChannel.open()
- .bind(new InetSocketAddress(0));
- listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
- public void completed(final AsynchronousSocketChannel ch, Void att) {
- listener.accept((Void)null, this);
- final ByteBuffer buf = ByteBuffer.allocate(100);
- ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
- public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
- if (bytesRead < 0) {
- try { ch.close(); } catch (IOException ignore) { }
- } else {
- buf.clear();
- ch.read(buf, ch, this);
- }
- }
- public void failed(Throwable exc, AsynchronousSocketChannel ch) {
- try { ch.close(); } catch (IOException ignore) { }
- }
- });
- }
- public void failed(Throwable exc, Void att) {
- }
- });
- int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
- SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
-
// create 3-10 channels, each in its own group
final int groupCount = 3 + rand.nextInt(8);
- AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount];
+ final AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount];
final AsynchronousSocketChannel[] channels = new AsynchronousSocketChannel[groupCount];
- for (int i=0; i<groupCount; i++) {
- ThreadFactory factory = createThreadFactory(i);
- AsynchronousChannelGroup group;
- if (rand.nextBoolean()) {
- int nThreads = 1 + rand.nextInt(10);
- group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
- } else {
- ExecutorService pool = Executors.newCachedThreadPool(factory);
- group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
- }
- groups[i] = group;
+
+ // create listener to accept connections
+ try (final AsynchronousServerSocketChannel listener =
+ AsynchronousServerSocketChannel.open()) {
- // create channel in group and connect it to the server
- AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
- ch.connect(sa).get();
- channels[i] = ch;
- }
+ listener.bind(new InetSocketAddress(0));
+ listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+ public void completed(final AsynchronousSocketChannel ch, Void att) {
+ listener.accept((Void)null, this);
+ final ByteBuffer buf = ByteBuffer.allocate(100);
+ ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
+ public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
+ if (bytesRead < 0) {
+ try { ch.close(); } catch (IOException ignore) { }
+ } else {
+ buf.clear();
+ ch.read(buf, ch, this);
+ }
+ }
+ public void failed(Throwable exc, AsynchronousSocketChannel ch) {
+ try { ch.close(); } catch (IOException ignore) { }
+ }
+ });
+ }
+ public void failed(Throwable exc, Void att) {
+ }
+ });
+ int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+ SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
- // randomly write to each channel, ensuring that the completion handler
- // is always invoked by a thread with the right identity.
- final AtomicInteger writeCount = new AtomicInteger(100);
- channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
- public void completed(Integer bytesWritten, Integer groupId) {
- if (bytesWritten != 1)
- fail("Expected 1 byte to be written");
- if (!myGroup.get().equals(groupId))
- fail("Handler invoked by thread with the wrong identity");
- if (writeCount.decrementAndGet() > 0) {
- int id = rand.nextInt(groupCount);
- channels[id].write(getBuffer(), id, this);
+ for (int i=0; i<groupCount; i++) {
+ ThreadFactory factory = createThreadFactory(i);
+ AsynchronousChannelGroup group;
+ if (rand.nextBoolean()) {
+ int nThreads = 1 + rand.nextInt(10);
+ group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
} else {
- done.countDown();
+ ExecutorService pool = Executors.newCachedThreadPool(factory);
+ group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
}
+ groups[i] = group;
+
+ // create channel in group and connect it to the server
+ AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+ ch.connect(sa).get();
+ channels[i] = ch;
}
- public void failed(Throwable exc, Integer groupId) {
- fail(exc.getMessage());
- }
- });
-
- // wait until done
- done.await();
- // clean-up
- for (AsynchronousSocketChannel ch: channels)
- ch.close();
- for (AsynchronousChannelGroup group: groups)
- group.shutdownNow();
- listener.close();
+ // randomly write to each channel, ensuring that the completion handler
+ // is always invoked by a thread with the right identity.
+ final AtomicInteger writeCount = new AtomicInteger(100);
+ channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
+ public void completed(Integer bytesWritten, Integer groupId) {
+ if (bytesWritten != 1)
+ fail("Expected 1 byte to be written");
+ if (!myGroup.get().equals(groupId))
+ fail("Handler invoked by thread with the wrong identity");
+ if (writeCount.decrementAndGet() > 0) {
+ int id = rand.nextInt(groupCount);
+ channels[id].write(getBuffer(), id, this);
+ } else {
+ done.countDown();
+ }
+ }
+ public void failed(Throwable exc, Integer groupId) {
+ fail(exc.getMessage());
+ }
+ });
- if (failed.get())
- throw new RuntimeException("Test failed - see log for details");
+ // wait until done
+ done.await();
+ } finally {
+ // clean-up
+ for (AsynchronousSocketChannel ch: channels)
+ ch.close();
+ for (AsynchronousChannelGroup group: groups)
+ group.shutdownNow();
+
+ if (failed.get())
+ throw new RuntimeException("Test failed - see log for details");
+ }
}
static ByteBuffer getBuffer() {
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,21 +66,30 @@
// group with fixed thread pool
int nThreads = 1 + rand.nextInt(4);
AsynchronousChannelGroup group =
- AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
- testRestart(group, 100);
- group.shutdown();
+ AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
+ try {
+ testRestart(group, 100);
+ } finally {
+ group.shutdown();
+ }
// group with cached thread pool
ExecutorService pool = Executors.newCachedThreadPool(factory);
group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
- testRestart(group, 100);
- group.shutdown();
+ try {
+ testRestart(group, 100);
+ } finally {
+ group.shutdown();
+ }
// group with custom thread pool
- group = AsynchronousChannelGroup
- .withThreadPool(Executors.newFixedThreadPool(1+rand.nextInt(5), factory));
- testRestart(group, 100);
- group.shutdown();
+ group = AsynchronousChannelGroup.withThreadPool(
+ Executors.newFixedThreadPool(1+rand.nextInt(5), factory));
+ try {
+ testRestart(group, 100);
+ } finally {
+ group.shutdown();
+ }
// give time for threads to terminate
Thread.sleep(3000);
@@ -92,45 +101,43 @@
static void testRestart(AsynchronousChannelGroup group, int count)
throws Exception
{
- AsynchronousServerSocketChannel listener =
- AsynchronousServerSocketChannel.open(group)
- .bind(new InetSocketAddress(0));
+ try (AsynchronousServerSocketChannel listener =
+ AsynchronousServerSocketChannel.open(group)) {
- for (int i=0; i<count; i++) {
- final CountDownLatch latch = new CountDownLatch(1);
+ listener.bind(new InetSocketAddress(0));
+ for (int i=0; i<count; i++) {
+ final CountDownLatch latch = new CountDownLatch(1);
- listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
- public void completed(AsynchronousSocketChannel ch, Void att) {
- try {
- ch.close();
- } catch (IOException ignore) { }
+ listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+ public void completed(AsynchronousSocketChannel ch, Void att) {
+ try {
+ ch.close();
+ } catch (IOException ignore) { }
- latch.countDown();
+ latch.countDown();
- // throw error or runtime exception
- if (rand.nextBoolean()) {
- throw new Error();
- } else {
- throw new RuntimeException();
+ // throw error or runtime exception
+ if (rand.nextBoolean()) {
+ throw new Error();
+ } else {
+ throw new RuntimeException();
+ }
}
- }
- public void failed(Throwable exc, Void att) {
- }
- });
+ public void failed(Throwable exc, Void att) {
+ }
+ });
- // establish loopback connection which should cause completion
- // handler to be invoked.
- int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
- AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
- InetAddress lh = InetAddress.getLocalHost();
- ch.connect(new InetSocketAddress(lh, port)).get();
- ch.close();
+ // establish loopback connection which should cause completion
+ // handler to be invoked.
+ int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+ try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
+ InetAddress lh = InetAddress.getLocalHost();
+ ch.connect(new InetSocketAddress(lh, port)).get();
+ }
- // wait for handler to be invoked
- latch.await();
+ // wait for handler to be invoked
+ latch.await();
+ }
}
-
- // clean-up
- listener.close();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/Lock.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/channels/FileChannel/Lock.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*/
/* @test
- * @bug 4429043 4493595 6332756 6709457
- * @summary The FileChannel file locking
+ * @bug 4429043 4493595 6332756 6709457 7146506
+ * @summary Test FileChannel file locking
*/
import java.io.*;
@@ -33,17 +33,14 @@
/**
* Testing FileChannel's lock method.
*/
-
public class Lock {
public static void main(String[] args) throws Exception {
- if (args.length > 0) {
- if(args[0].equals("1")) {
- MadWriter mw = new MadWriter(args[1], false);
- } else {
- MadWriter mw = new MadWriter(args[1], true);
- }
+ if (args.length == 2) {
+ attemptLock(args[1], args[0].equals("2"));
return;
+ } else if (args.length != 0) {
+ throw new RuntimeException("Wrong number of parameters.");
}
File blah = File.createTempFile("blah", null);
blah.deleteOnExit();
@@ -56,120 +53,128 @@
test2(blah, false);
test3(blah);
test4(blah);
- blah.delete();
- }
-
- private static void test2(File blah, boolean b) throws Exception {
- RandomAccessFile raf = new RandomAccessFile(blah, "rw");
- FileChannel channel = raf.getChannel();
- FileLock lock;
- if (b)
- lock = channel.lock();
- else
- lock = channel.tryLock();
- lock.release();
- channel.close();
}
+ /**
+ * Test mutual locking with other process
+ */
static void test1(File blah, String str) throws Exception {
+ try (RandomAccessFile fis = new RandomAccessFile(blah, "rw")) {
+ FileChannel fc = fis.getChannel();
+ FileLock lock = null;
- // Grab the lock
- RandomAccessFile fis = new RandomAccessFile(blah, "rw");
- FileChannel fc = fis.getChannel();
- FileLock lock = null;
+ // grab the lock
+ if (str.equals("1")) {
+ lock = fc.lock(0, 10, false);
+ if (lock == null)
+ throw new RuntimeException("Lock should not return null");
+ try {
+ fc.lock(5, 10, false);
+ throw new RuntimeException("Overlapping locks allowed");
+ } catch (OverlappingFileLockException e) {} // correct result
+ }
+
+ // execute the tamperer
+ String command = System.getProperty("java.home") +
+ File.separator + "bin" + File.separator + "java";
+ String testClasses = System.getProperty("test.classes");
+ if (testClasses != null)
+ command += " -cp " + testClasses;
+ command += " Lock " + str + " " + blah;
+ Process p = Runtime.getRuntime().exec(command);
- if (str.equals("1")) {
- lock = fc.lock(0, 10, false);
- if (lock == null)
- throw new RuntimeException("Lock should not return null");
- try {
- FileLock lock2 = fc.lock(5, 10, false);
- throw new RuntimeException("Overlapping locks allowed");
- } catch (OverlappingFileLockException e) {
- // Correct result
+ // evaluate System.out of child process
+ String s;
+ boolean hasOutput = false;
+ InputStreamReader isr;
+ isr = new InputStreamReader(p.getInputStream());
+ BufferedReader br = new BufferedReader(isr);
+ while ((s = br.readLine()) != null) {
+ // only throw on Unix as windows over NFS fails...
+ if ((File.separatorChar == '/') && !s.equals("good")) {
+ throw new RuntimeException("Failed: " + s);
+ }
+ hasOutput = true;
+ }
+
+ // evaluate System.err in case of System.out of child process
+ // was empty
+ if (!hasOutput) {
+ isr = new InputStreamReader(p.getErrorStream());
+ br = new BufferedReader(isr);
+ if ((s = br.readLine()) != null) {
+ System.err.println("Error output:");
+ System.err.println(s);
+ while ((s = br.readLine()) != null) {
+ System.err.println(s);
+ }
+ }
+ throw new RuntimeException("Failed, no output");
+ }
+
+ // clean up, check multiple releases
+ if (lock != null) {
+ lock.release();
+ lock.release();
}
}
-
- // Exec the tamperer
- String command = System.getProperty("java.home") +
- File.separator + "bin" + File.separator + "java";
- String testClasses = System.getProperty("test.classes");
- if (testClasses != null)
- command += " -cp " + testClasses;
- command += " Lock " + str + " " + blah;
- Process p = Runtime.getRuntime().exec(command);
-
- BufferedReader in = new BufferedReader
- (new InputStreamReader(p.getInputStream()));
+ }
- String s;
- int count = 0;
- while ((s = in.readLine()) != null) {
- if (!s.equals("good")) {
- if (File.separatorChar == '/') {
- // Fails on windows over NFS...
- throw new RuntimeException("Failed: "+s);
- }
- }
- count++;
- }
-
- if (count == 0) {
- in = new BufferedReader(new InputStreamReader(p.getErrorStream()));
- while ((s = in.readLine()) != null) {
- System.err.println("Error output: " + s);
- }
- throw new RuntimeException("Failed, no output");
- }
-
- // Clean up
- if (lock != null) {
- /* Check multiple releases */
- lock.release();
+ /**
+ * Basic test for FileChannel.lock() and FileChannel.tryLock()
+ */
+ static void test2(File blah, boolean b) throws Exception {
+ try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {
+ FileChannel channel = raf.getChannel();
+ FileLock lock;
+ if (b)
+ lock = channel.lock();
+ else
+ lock = channel.tryLock();
lock.release();
}
- fc.close();
- fis.close();
}
- // The overlap check for file locks should be JVM-wide
- private static void test3(File blah) throws Exception {
- FileChannel fc1 = new RandomAccessFile(blah, "rw").getChannel();
- FileChannel fc2 = new RandomAccessFile(blah, "rw").getChannel();
+ /**
+ * Test that overlapping file locking is not possible when using different
+ * FileChannel objects to the same file path
+ */
+ static void test3(File blah) throws Exception {
+ try (RandomAccessFile raf1 = new RandomAccessFile(blah, "rw");
+ RandomAccessFile raf2 = new RandomAccessFile(blah, "rw"))
+ {
+ FileChannel fc1 = raf1.getChannel();
+ FileChannel fc2 = raf2.getChannel();
- // lock via one channel, and then attempt to lock the same file
- // using a second channel
- FileLock fl1 = fc1.lock();
- try {
- fc2.tryLock();
- throw new RuntimeException("Overlapping locks allowed");
- } catch (OverlappingFileLockException x) {
- }
- try {
+ // lock via one channel, and then attempt to lock the same file
+ // using a second channel
+ FileLock fl1 = fc1.lock();
+ try {
+ fc2.tryLock();
+ throw new RuntimeException("Overlapping locks allowed");
+ } catch (OverlappingFileLockException x) {}
+ try {
+ fc2.lock();
+ throw new RuntimeException("Overlapping locks allowed");
+ } catch (OverlappingFileLockException x) {}
+
+ // release lock and the attempt to lock with the second channel
+ // should succeed.
+ fl1.release();
fc2.lock();
- throw new RuntimeException("Overlapping locks allowed");
- } catch (OverlappingFileLockException x) {
+ try {
+ fc1.lock();
+ throw new RuntimeException("Overlapping locks allowed");
+ } catch (OverlappingFileLockException x) {}
}
-
- // release lock and the attempt to lock with the second channel
- // should succeed.
- fl1.release();
- FileLock fl2 = fc2.lock();
- try {
- fc1.lock();
- throw new RuntimeException("Overlapping locks allowed");
- } catch (OverlappingFileLockException x) {
- }
-
- fc1.close();
- fc2.close();
}
/**
* Test file locking when file is opened for append
*/
static void test4(File blah) throws Exception {
- try (FileChannel fc = new FileOutputStream(blah, true).getChannel()) {
+ try (FileOutputStream fos = new FileOutputStream(blah, true)) {
+ FileChannel fc = fos.getChannel();
fc.tryLock().release();
fc.tryLock(0L, 1L, false).release();
fc.lock().release();
@@ -182,30 +187,31 @@
fc.lock(0L, 1L, false).release();
}
}
-}
-class MadWriter {
- public MadWriter(String s, boolean b) throws Exception {
- File f = new File(s);
- RandomAccessFile fos = new RandomAccessFile(f, "rw");
- FileChannel fc = fos.getChannel();
- if (fc.tryLock(10, 10, false) == null) {
- System.out.println("bad: Failed to grab adjacent lock");
+ /**
+ * Utility method to be run in secondary process which tries to acquire a
+ * lock on a FileChannel
+ */
+ static void attemptLock(String fileName,
+ boolean expectsLock) throws Exception
+ {
+ File f = new File(fileName);
+ try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) {
+ FileChannel fc = raf.getChannel();
+ if (fc.tryLock(10, 10, false) == null) {
+ System.out.println("bad: Failed to grab adjacent lock");
+ }
+ if (fc.tryLock(0, 10, false) == null) {
+ if (expectsLock)
+ System.out.println("bad");
+ else
+ System.out.println("good");
+ } else {
+ if (expectsLock)
+ System.out.println("good");
+ else
+ System.out.println("bad");
+ }
}
- FileLock lock = fc.tryLock(0, 10, false);
- if (lock == null) {
- if (b)
- System.out.println("bad");
- else
- System.out.println("good");
- } else {
- if (b)
- System.out.println("good");
- else
- System.out.println("bad");
- }
- fc.close();
- fos.close();
}
-
}
--- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java Wed Jul 05 22:08:15 2017 +0200
@@ -95,7 +95,7 @@
return 0;
}
- static int checkContentTypes(String[] extensions, String[][] expectedTypes)
+ static int checkContentTypes(String[] extensions, String[] expectedTypes)
throws IOException {
if (extensions.length != expectedTypes.length) {
System.err.println("Parameter array lengths differ");
@@ -112,27 +112,10 @@
System.err.println("Content type of " + extension
+ " cannot be determined");
failures++;
- } else {
- boolean isTypeFound = false;
- for (String s : expectedTypes[i]) {
- if (type.equals(s)) {
- isTypeFound = true;
- break;
- }
- }
- if (!isTypeFound) {
- System.err.printf("Content type: %s; expected: ", type);
- int j = 0;
- for (String s : expectedTypes[i]) {
- if (j++ == 0) {
- System.err.printf("%s", s);
- } else {
- System.err.printf(", or %s", s);
- }
- }
- System.err.println();
- failures++;
- }
+ } else if (!type.equals(expectedTypes[i])) {
+ System.err.printf("Content type: %s; expected: %s%n",
+ type, expectedTypes);
+ failures++;
}
} finally {
Files.delete(file);
@@ -174,8 +157,6 @@
// Verify that certain media extensions are mapped to the correct type.
String[] extensions = new String[]{
- "aac",
- "flac",
"jpg",
"mp3",
"mp4",
@@ -183,15 +164,13 @@
"png",
"webm"
};
- String[][] expectedTypes = new String[][] {
- {"audio/aac", "audio/x-aac", "audio/vnd.dlna.adts"},
- {"audio/flac", "audio/x-flac"},
- {"image/jpeg"},
- {"audio/mpeg"},
- {"video/mp4"},
- {"application/pdf"},
- {"image/png"},
- {"video/webm"}
+ String[] expectedTypes = new String[] {
+ "image/jpeg",
+ "audio/mpeg",
+ "video/mp4",
+ "application/pdf",
+ "image/png",
+ "video/webm"
};
failures += checkContentTypes(extensions, expectedTypes);
--- a/jdk/test/java/nio/file/Path/PathOps.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/file/Path/PathOps.java Wed Jul 05 22:08:15 2017 +0200
@@ -197,6 +197,19 @@
return this;
}
+ PathOps relativizeFail(String other) {
+ out.format("test relativize %s\n", other);
+ checkPath();
+ Path that = FileSystems.getDefault().getPath(other);
+ try {
+ Path result = path.relativize(that);
+ out.format("\tExpected: IllegalArgumentException");
+ out.format("\tActual: %s\n", result);
+ fail();
+ } catch (IllegalArgumentException expected) { }
+ return this;
+ }
+
PathOps normalize(String expected) {
out.println("check normalized path");
checkPath();
@@ -572,29 +585,709 @@
.resolveSibling("C:\\", "C:\\");
// relativize
- test("foo")
- .relativize("foo", "")
- .relativize("bar", "..\\bar")
+ test("C:\\a")
+ .relativize("C:\\a", "")
+ .relativize("C:\\", "..")
+ .relativize("C:\\.", "..")
+ .relativize("C:\\..", "..")
+ .relativize("C:\\..\\..", "..")
+ .relativize("C:\\a\\b", "b")
+ .relativize("C:\\a\\b\\c", "b\\c")
+ .relativize("C:\\a\\.", "") // "." also valid
+ .relativize("C:\\a\\..", "..")
+ .relativize("C:\\x", "..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\a\\b")
+ .relativize("C:\\a\\b", "")
+ .relativize("C:\\a", "..")
+ .relativize("C:\\", "..\\..")
+ .relativize("C:\\.", "..\\..")
+ .relativize("C:\\..", "..\\..")
+ .relativize("C:\\..\\..", "..\\..")
+ .relativize("C:\\a\\b\\c", "c")
+ .relativize("C:\\a\\.", "..")
+ .relativize("C:\\a\\..", "..\\..")
+ .relativize("C:\\x", "..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\a\\b\\c")
+ .relativize("C:\\a\\b\\c", "")
+ .relativize("C:\\a\\b", "..")
+ .relativize("C:\\a", "..\\..")
+ .relativize("C:\\", "..\\..\\..")
+ .relativize("C:\\.", "..\\..\\..")
+ .relativize("C:\\..", "..\\..\\..")
+ .relativize("C:\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\a\\b\\c\\d", "d")
+ .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("C:\\a\\b\\c\\.", "") // "." also valid
+ .relativize("C:\\a\\b\\c\\..", "..")
+ .relativize("C:\\a\\x", "..\\..\\x")
+ .relativize("C:\\x", "..\\..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\a")
+ .relativize("C:\\a", "")
+ .relativize("C:\\", "..")
+ .relativize("C:\\.", "..")
+ .relativize("C:\\..", "..")
+ .relativize("C:\\..\\..", "..")
+ .relativize("C:\\a\\b", "b")
+ .relativize("C:\\a\\b\\c", "b\\c")
+ .relativize("C:\\a\\.", "") // "." also valid
+ .relativize("C:\\a\\..", "..")
+ .relativize("C:\\x", "..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\a\\b")
+ .relativize("C:\\a\\b", "")
+ .relativize("C:\\a", "..")
+ .relativize("C:\\", "..\\..")
+ .relativize("C:\\.", "..\\..")
+ .relativize("C:\\..", "..\\..")
+ .relativize("C:\\..\\..", "..\\..")
+ .relativize("C:\\..\\..\\..", "..\\..")
+ .relativize("C:\\..\\..\\..\\..", "..\\..")
+ .relativize("C:\\a\\b\\c", "c")
+ .relativize("C:\\a\\b\\.", "") // "." also valid
+ .relativize("C:\\a\\b\\..", "..")
+ .relativize("C:\\a\\x", "..\\x")
+ .relativize("C:\\x", "..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\..\\a\\b")
+ .relativize("C:\\a\\b", "")
+ .relativize("C:\\a", "..")
+ .relativize("C:\\", "..\\..")
+ .relativize("C:\\.", "..\\..")
+ .relativize("C:\\..", "..\\..")
+ .relativize("C:\\..\\..", "..\\..")
+ .relativize("C:\\..\\..\\..", "..\\..")
+ .relativize("C:\\..\\..\\..\\..", "..\\..")
+ .relativize("C:\\a\\b\\c", "c")
+ .relativize("C:\\a\\b\\.", "") // "." also valid
+ .relativize("C:\\a\\b\\..", "..")
+ .relativize("C:\\a\\x", "..\\x")
+ .relativize("C:\\x", "..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\a\\b\\c")
+ .relativize("C:\\a\\b\\c", "")
+ .relativize("C:\\a\\b", "..")
+ .relativize("C:\\a", "..\\..")
+ .relativize("C:\\", "..\\..\\..")
+ .relativize("C:\\.", "..\\..\\..")
+ .relativize("C:\\..", "..\\..\\..")
+ .relativize("C:\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\a\\b\\c\\d", "d")
+ .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("C:\\a\\b\\c\\.", "") // "." also valid
+ .relativize("C:\\a\\b\\c\\..", "..")
+ .relativize("C:\\a\\x", "..\\..\\x")
+ .relativize("C:\\x", "..\\..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\..\\a\\b\\c")
+ .relativize("C:\\a\\b\\c", "")
+ .relativize("C:\\a\\b", "..")
+ .relativize("C:\\a", "..\\..")
+ .relativize("C:\\", "..\\..\\..")
+ .relativize("C:\\.", "..\\..\\..")
+ .relativize("C:\\..", "..\\..\\..")
+ .relativize("C:\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\a\\b\\c\\d", "d")
+ .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("C:\\a\\b\\c\\.", "") // "." also valid
+ .relativize("C:\\a\\b\\c\\..", "..")
+ .relativize("C:\\a\\x", "..\\..\\x")
+ .relativize("C:\\x", "..\\..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\..\\..\\a\\b\\c")
+ .relativize("C:\\a\\b\\c", "")
+ .relativize("C:\\a\\b", "..")
+ .relativize("C:\\a", "..\\..")
+ .relativize("C:\\", "..\\..\\..")
+ .relativize("C:\\.", "..\\..\\..")
+ .relativize("C:\\..", "..\\..\\..")
+ .relativize("C:\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("C:\\a\\b\\c\\d", "d")
+ .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("C:\\a\\b\\c\\.", "") // "." also valid
+ .relativize("C:\\a\\b\\c\\..", "..")
+ .relativize("C:\\a\\x", "..\\..\\x")
+ .relativize("C:\\x", "..\\..\\..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\.\\a")
+ .relativize("C:\\a", "")
+ .relativize("C:\\", "..")
+ .relativize("C:\\.", "..")
+ .relativize("C:\\..", "..")
+ .relativize("C:\\..\\..", "..")
+ .relativize("C:\\a\\b", "b")
+ .relativize("C:\\a\\b\\c", "b\\c")
+ .relativize("C:\\a\\.", "") // "." also valid
+ .relativize("C:\\a\\..", "..")
+ .relativize("C:\\x", "..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\..\\a")
+ .relativize("C:\\a", "")
+ .relativize("C:\\", "..")
+ .relativize("C:\\.", "..")
+ .relativize("C:\\..", "..")
+ .relativize("C:\\..\\..", "..")
+ .relativize("C:\\a\\b", "b")
+ .relativize("C:\\a\\b\\c", "b\\c")
+ .relativize("C:\\a\\.", "") // "." also valid
+ .relativize("C:\\a\\..", "..")
+ .relativize("C:\\x", "..\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:\\a\\..")
+ .relativize("C:\\a", "a")
+ .relativize("C:\\", "") // "." is also valid
+ .relativize("C:\\.", "")
+ .relativize("C:\\..", "")
+ .relativize("C:\\..\\..", "")
+ .relativize("C:\\a\\.", "a")
+ .relativize("C:\\a\\..", "")
+ .relativize("C:\\x", "x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("C:a")
+ .relativize("C:a", "")
+ .relativize("C:", "..")
+ .relativize("C:.", "..")
+ .relativize("C:..", "..\\..")
+ .relativize("C:..\\..", "..\\..\\..")
+ .relativize("C:.\\..", "..\\..")
+ .relativize("C:a\\b", "b")
+ .relativize("C:a\\b\\c", "b\\c")
+ .relativize("C:..\\x", "..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("C:a\\b")
+ .relativize("C:a\\b", "")
+ .relativize("C:a", "..")
+ .relativize("C:", "..\\..")
+ .relativize("C:.", "..\\..")
+ .relativize("C:..", "..\\..\\..")
+ .relativize("C:..\\..", "..\\..\\..\\..")
+ .relativize("C:.\\..", "..\\..\\..")
+ .relativize("C:a\\b\\c", "c")
+ .relativize("C:..\\x", "..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("C:a\\b\\c")
+ .relativize("C:a\\b\\c", "")
+ .relativize("C:a\\b", "..")
+ .relativize("C:a", "..\\..")
+ .relativize("C:", "..\\..\\..")
+ .relativize("C:.", "..\\..\\..")
+ .relativize("C:..", "..\\..\\..\\..")
+ .relativize("C:..\\..", "..\\..\\..\\..\\..")
+ .relativize("C:.\\..", "..\\..\\..\\..")
+ .relativize("C:a\\b\\c\\d", "d")
+ .relativize("C:a\\b\\c\\d\\e", "d\\e")
+ .relativize("C:a\\x", "..\\..\\x")
+ .relativize("C:..\\x", "..\\..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("C:")
+ .relativize("C:a", "a")
+ .relativize("C:a\\b\\c", "a\\b\\c")
+ .relativize("C:", "")
+ .relativize("C:.", "") // "" also valid
+ .relativize("C:..", "..")
+ .relativize("C:..\\..", "..\\..")
+ .relativize("C:.\\..", "..")
+ .relativizeFail("C:\\x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("C:..")
+ .relativize("C:..\\a", "a")
+ .relativize("C:..", "")
+ .relativize("C:.\\..", "")
+ .relativizeFail("C:\\x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("x");
+ test("C:..\\a")
+ .relativize("C:..\\a\\b", "b")
+ .relativize("C:..\\a", "")
+ .relativize("C:..", "..")
+ .relativize("C:.\\..", "..")
+ .relativizeFail("C:\\x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("x");
+ test("C:..\\a\\b")
+ .relativize("C:..\\a\\b\\c", "c")
+ .relativize("C:..\\a\\b", "")
+ .relativize("C:..\\a", "..")
+ .relativize("C:..", "..\\..")
+ .relativize("C:.\\..", "..\\..")
+ .relativizeFail("C:\\x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("")
+ .relativizeFail("x");
+ test("C:a\\..")
+ .relativize("C:b", "b")
+ .relativize("C:", "")
+ .relativize("C:.", "") // "." also valid
+ .relativize("C:..", "..")
+ .relativize("C:a\\..\\b", "b")
+ .relativize("C:a\\..", "")
+ .relativize("C:..\\b", "..\\b")
+ .relativize("C:b\\..", "")
+ .relativizeFail("C:\\x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("x");
+ test("C:a\\..\\b")
+ .relativize("C:a\\..\\b", "")
+ .relativize("C:a\\..", "..")
+ .relativize("C:", "..")
+ .relativize("C:.", "..")
+ .relativize("C:..", "..\\..")
+ .relativize("C:b", "")
+ .relativize("C:c", "..\\c")
+ .relativize("C:..\\c", "..\\..\\c")
+ .relativize("C:a\\..\\b\\c", "c")
+ .relativizeFail("C:\\x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("x");
+ test("\\a")
+ .relativize("\\a", "")
+ .relativize("\\", "..")
+ .relativize("\\.", "..")
+ .relativize("\\..", "..")
+ .relativize("\\..\\..", "..")
+ .relativize("\\a\\b", "b")
+ .relativize("\\a\\b\\c", "b\\c")
+ .relativize("\\a\\.", "") // "." also valid
+ .relativize("\\a\\..", "..")
+ .relativize("\\x", "..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\a\\b")
+ .relativize("\\a\\b", "")
+ .relativize("\\a", "..")
+ .relativize("\\", "..\\..")
+ .relativize("\\.", "..\\..")
+ .relativize("\\..", "..\\..")
+ .relativize("\\..\\..", "..\\..")
+ .relativize("\\a\\b\\c", "c")
+ .relativize("\\a\\.", "..")
+ .relativize("\\a\\..", "..\\..")
+ .relativize("\\x", "..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\a\\b\\c")
+ .relativize("\\a\\b\\c", "")
+ .relativize("\\a\\b", "..")
+ .relativize("\\a", "..\\..")
+ .relativize("\\", "..\\..\\..")
+ .relativize("\\.", "..\\..\\..")
+ .relativize("\\..", "..\\..\\..")
+ .relativize("\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("\\a\\b\\c\\d", "d")
+ .relativize("\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("\\a\\b\\c\\.", "") // "." also valid
+ .relativize("\\a\\b\\c\\..", "..")
+ .relativize("\\a\\x", "..\\..\\x")
+ .relativize("\\x", "..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\a")
+ .relativize("\\a", "")
+ .relativize("\\", "..")
+ .relativize("\\.", "..")
+ .relativize("\\..", "..")
+ .relativize("\\..\\..", "..")
+ .relativize("\\a\\b", "b")
+ .relativize("\\a\\b\\c", "b\\c")
+ .relativize("\\a\\.", "") // "." also valid
+ .relativize("\\a\\..", "..")
+ .relativize("\\x", "..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\a\\b")
+ .relativize("\\a\\b", "")
+ .relativize("\\a", "..")
+ .relativize("\\", "..\\..")
+ .relativize("\\.", "..\\..")
+ .relativize("\\..", "..\\..")
+ .relativize("\\..\\..", "..\\..")
+ .relativize("\\..\\..\\..", "..\\..")
+ .relativize("\\..\\..\\..\\..", "..\\..")
+ .relativize("\\a\\b\\c", "c")
+ .relativize("\\a\\b\\.", "") // "." also valid
+ .relativize("\\a\\b\\..", "..")
+ .relativize("\\a\\x", "..\\x")
+ .relativize("\\x", "..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\..\\a\\b")
+ .relativize("\\a\\b", "")
+ .relativize("\\a", "..")
+ .relativize("\\", "..\\..")
+ .relativize("\\.", "..\\..")
+ .relativize("\\..", "..\\..")
+ .relativize("\\..\\..", "..\\..")
+ .relativize("\\..\\..\\..", "..\\..")
+ .relativize("\\..\\..\\..\\..", "..\\..")
+ .relativize("\\a\\b\\c", "c")
+ .relativize("\\a\\b\\.", "") // "." also valid
+ .relativize("\\a\\b\\..", "..")
+ .relativize("\\a\\x", "..\\x")
+ .relativize("\\x", "..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\a\\b\\c")
+ .relativize("\\a\\b\\c", "")
+ .relativize("\\a\\b", "..")
+ .relativize("\\a", "..\\..")
+ .relativize("\\", "..\\..\\..")
+ .relativize("\\.", "..\\..\\..")
+ .relativize("\\..", "..\\..\\..")
+ .relativize("\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("\\a\\b\\c\\d", "d")
+ .relativize("\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("\\a\\b\\c\\.", "") // "." also valid
+ .relativize("\\a\\b\\c\\..", "..")
+ .relativize("\\a\\x", "..\\..\\x")
+ .relativize("\\x", "..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\..\\a\\b\\c")
+ .relativize("\\a\\b\\c", "")
+ .relativize("\\a\\b", "..")
+ .relativize("\\a", "..\\..")
+ .relativize("\\", "..\\..\\..")
+ .relativize("\\.", "..\\..\\..")
+ .relativize("\\..", "..\\..\\..")
+ .relativize("\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("\\a\\b\\c\\d", "d")
+ .relativize("\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("\\a\\b\\c\\.", "") // "." also valid
+ .relativize("\\a\\b\\c\\..", "..")
+ .relativize("\\a\\x", "..\\..\\x")
+ .relativize("\\x", "..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\..\\..\\a\\b\\c")
+ .relativize("\\a\\b\\c", "")
+ .relativize("\\a\\b", "..")
+ .relativize("\\a", "..\\..")
+ .relativize("\\", "..\\..\\..")
+ .relativize("\\.", "..\\..\\..")
+ .relativize("\\..", "..\\..\\..")
+ .relativize("\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..", "..\\..\\..")
+ .relativize("\\..\\..\\..\\..", "..\\..\\..")
+ .relativize("\\a\\b\\c\\d", "d")
+ .relativize("\\a\\b\\c\\d\\e", "d\\e")
+ .relativize("\\a\\b\\c\\.", "") // "." also valid
+ .relativize("\\a\\b\\c\\..", "..")
+ .relativize("\\a\\x", "..\\..\\x")
+ .relativize("\\x", "..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\.\\a")
+ .relativize("\\a", "")
+ .relativize("\\", "..")
+ .relativize("\\.", "..")
+ .relativize("\\..", "..")
+ .relativize("\\..\\..", "..")
+ .relativize("\\a\\b", "b")
+ .relativize("\\a\\b\\c", "b\\c")
+ .relativize("\\a\\.", "") // "." also valid
+ .relativize("\\a\\..", "..")
+ .relativize("\\x", "..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\..\\a")
+ .relativize("\\a", "")
+ .relativize("\\", "..")
+ .relativize("\\.", "..")
+ .relativize("\\..", "..")
+ .relativize("\\..\\..", "..")
+ .relativize("\\a\\b", "b")
+ .relativize("\\a\\b\\c", "b\\c")
+ .relativize("\\a\\.", "") // "." also valid
+ .relativize("\\a\\..", "..")
+ .relativize("\\x", "..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\a\\..")
+ .relativize("\\a", "a")
+ .relativize("\\", "") // "." is also valid
+ .relativize("\\.", "")
+ .relativize("\\..", "")
+ .relativize("\\..\\..", "")
+ .relativize("\\a\\.", "a")
+ .relativize("\\a\\..", "")
+ .relativize("\\x", "x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("\\")
+ .relativize("\\a", "a")
+ .relativize("\\", "") // "." is also valid
+ .relativize("\\.", "")
+ .relativize("\\..", "")
+ .relativize("\\..\\..", "")
+ .relativize("\\a\\.", "a")
+ .relativize("\\a\\..", "")
+ .relativize("\\x", "x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("a")
+ .relativize("a", "")
+ .relativize("", "..")
+ .relativize(".", "..")
.relativize("..", "..\\..")
- .relativize("", "..");
- test("foo\\bar")
- .relativize("foo\\bar", "")
- .relativize("foo", "..")
- .relativize("gus", "..\\..\\gus")
+ .relativize("..\\..", "..\\..\\..")
+ .relativize(".\\..", "..\\..")
+ .relativize("a\\b", "b")
+ .relativize("a\\b\\c", "b\\c")
+ .relativize("..\\x", "..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("a\\b")
+ .relativize("a\\b", "")
+ .relativize("a", "..")
+ .relativize("", "..\\..")
+ .relativize(".", "..\\..")
.relativize("..", "..\\..\\..")
- .relativize("", "..\\..");
- test("C:\\a\\b\\c")
- .relativize("C:\\a", "..\\..")
- .relativize("C:\\a\\b\\c", "")
- .relativize("C:\\x", "..\\..\\..\\x");
- test("\\\\server\\share\\foo")
- .relativize("\\\\server\\share\\bar", "..\\bar")
- .relativize("\\\\server\\share\\foo", "");
+ .relativize("..\\..", "..\\..\\..\\..")
+ .relativize(".\\..", "..\\..\\..")
+ .relativize("a\\b\\c", "c")
+ .relativize("..\\x", "..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("a\\b\\c")
+ .relativize("a\\b\\c", "")
+ .relativize("a\\b", "..")
+ .relativize("a", "..\\..")
+ .relativize("", "..\\..\\..")
+ .relativize(".", "..\\..\\..")
+ .relativize("..", "..\\..\\..\\..")
+ .relativize("..\\..", "..\\..\\..\\..\\..")
+ .relativize(".\\..", "..\\..\\..\\..")
+ .relativize("a\\b\\c\\d", "d")
+ .relativize("a\\b\\c\\d\\e", "d\\e")
+ .relativize("a\\x", "..\\..\\x")
+ .relativize("..\\x", "..\\..\\..\\..\\x")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
test("")
.relativize("a", "a")
.relativize("a\\b\\c", "a\\b\\c")
+ .relativize("", "")
+ .relativize(".", ".")
.relativize("..", "..")
- .relativize("", "");
+ .relativize("..\\..", "..\\..")
+ .relativize(".\\..", ".\\..") // ".." also valid
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("..")
+ .relativize("..\\a", "a")
+ .relativize("..", "")
+ .relativize(".\\..", "")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("x");
+ test("..\\a")
+ .relativize("..\\a\\b", "b")
+ .relativize("..\\a", "")
+ .relativize("..", "..")
+ .relativize(".\\..", "..")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("x");
+ test("..\\a\\b")
+ .relativize("..\\a\\b\\c", "c")
+ .relativize("..\\a\\b", "")
+ .relativize("..\\a", "..")
+ .relativize("..", "..\\..")
+ .relativize(".\\..", "..\\..")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x")
+ .relativizeFail("")
+ .relativizeFail("x");
+ test("a\\..")
+ .relativize("b", "b")
+ .relativize("", "")
+ .relativize(".", "") // "." also valid
+ .relativize("..", "..")
+ .relativize("a\\..\\b", "b")
+ .relativize("a\\..", "")
+ .relativize("..\\b", "..\\b")
+ .relativize("b\\..", "")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
+ test("a\\..\\b")
+ .relativize("a\\..\\b", "")
+ .relativize("a\\..", "..")
+ .relativize("", "..")
+ .relativize(".", "..")
+ .relativize("..", "..\\..")
+ .relativize("b", "")
+ .relativize("c", "..\\c")
+ .relativize("..\\c", "..\\..\\c")
+ .relativize("a\\..\\b\\c", "c")
+ .relativizeFail("C:\\x")
+ .relativizeFail("C:x")
+ .relativizeFail("\\")
+ .relativizeFail("\\x");
// normalize
test("C:\\")
@@ -971,20 +1664,324 @@
.resolve("", "");
// relativize
+ test("/a")
+ .relativize("/a", "")
+ .relativize("/", "..")
+ .relativize("/.", "..")
+ .relativize("/..", "..")
+ .relativize("/../..", "..")
+ .relativize("/a/b", "b")
+ .relativize("/a/b/c", "b/c")
+ .relativize("/a/.", "") // "." also valid
+ .relativize("/a/..", "..")
+ .relativize("/x", "../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/a/b")
+ .relativize("/a/b", "")
+ .relativize("/a", "..")
+ .relativize("/", "../..")
+ .relativize("/.", "../..")
+ .relativize("/..", "../..")
+ .relativize("/../..", "../..")
+ .relativize("/a/b/c", "c")
+ .relativize("/a/.", "..")
+ .relativize("/a/..", "../..")
+ .relativize("/x", "../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
test("/a/b/c")
.relativize("/a/b/c", "")
+ .relativize("/a/b", "..")
+ .relativize("/a", "../..")
+ .relativize("/", "../../..")
+ .relativize("/.", "../../..")
+ .relativize("/..", "../../..")
+ .relativize("/../..", "../../..")
+ .relativize("/../../..", "../../..")
+ .relativize("/../../../..", "../../..")
+ .relativize("/a/b/c/d", "d")
.relativize("/a/b/c/d/e", "d/e")
+ .relativize("/a/b/c/.", "") // "." also valid
+ .relativize("/a/b/c/..", "..")
+ .relativize("/a/x", "../../x")
+ .relativize("/x", "../../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../a")
+ .relativize("/a", "")
+ .relativize("/", "..")
+ .relativize("/.", "..")
+ .relativize("/..", "..")
+ .relativize("/../..", "..")
+ .relativize("/a/b", "b")
+ .relativize("/a/b/c", "b/c")
+ .relativize("/a/.", "") // "." also valid
+ .relativize("/a/..", "..")
+ .relativize("/x", "../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../a/b")
+ .relativize("/a/b", "")
+ .relativize("/a", "..")
+ .relativize("/", "../..")
+ .relativize("/.", "../..")
+ .relativize("/..", "../..")
+ .relativize("/../..", "../..")
+ .relativize("/../../..", "../..")
+ .relativize("/../../../..", "../..")
+ .relativize("/a/b/c", "c")
+ .relativize("/a/b/.", "") // "." also valid
+ .relativize("/a/b/..", "..")
+ .relativize("/a/x", "../x")
+ .relativize("/x", "../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../../a/b")
+ .relativize("/a/b", "")
+ .relativize("/a", "..")
+ .relativize("/", "../..")
+ .relativize("/.", "../..")
+ .relativize("/..", "../..")
+ .relativize("/../..", "../..")
+ .relativize("/../../..", "../..")
+ .relativize("/../../../..", "../..")
+ .relativize("/a/b/c", "c")
+ .relativize("/a/b/.", "") // "." also valid
+ .relativize("/a/b/..", "..")
+ .relativize("/a/x", "../x")
+ .relativize("/x", "../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../a/b/c")
+ .relativize("/a/b/c", "")
+ .relativize("/a/b", "..")
+ .relativize("/a", "../..")
+ .relativize("/", "../../..")
+ .relativize("/.", "../../..")
+ .relativize("/..", "../../..")
+ .relativize("/../..", "../../..")
+ .relativize("/../../..", "../../..")
+ .relativize("/../../../..", "../../..")
+ .relativize("/a/b/c/d", "d")
+ .relativize("/a/b/c/d/e", "d/e")
+ .relativize("/a/b/c/.", "") // "." also valid
+ .relativize("/a/b/c/..", "..")
+ .relativize("/a/x", "../../x")
+ .relativize("/x", "../../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../../a/b/c")
+ .relativize("/a/b/c", "")
+ .relativize("/a/b", "..")
+ .relativize("/a", "../..")
+ .relativize("/", "../../..")
+ .relativize("/.", "../../..")
+ .relativize("/..", "../../..")
+ .relativize("/../..", "../../..")
+ .relativize("/../../..", "../../..")
+ .relativize("/../../../..", "../../..")
+ .relativize("/a/b/c/d", "d")
+ .relativize("/a/b/c/d/e", "d/e")
+ .relativize("/a/b/c/.", "") // "." also valid
+ .relativize("/a/b/c/..", "..")
.relativize("/a/x", "../../x")
- .relativize("/x", "../../../x");
+ .relativize("/x", "../../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../../../a/b/c")
+ .relativize("/a/b/c", "")
+ .relativize("/a/b", "..")
+ .relativize("/a", "../..")
+ .relativize("/", "../../..")
+ .relativize("/.", "../../..")
+ .relativize("/..", "../../..")
+ .relativize("/../..", "../../..")
+ .relativize("/../../..", "../../..")
+ .relativize("/../../../..", "../../..")
+ .relativize("/a/b/c/d", "d")
+ .relativize("/a/b/c/d/e", "d/e")
+ .relativize("/a/b/c/.", "") // "." also valid
+ .relativize("/a/b/c/..", "..")
+ .relativize("/a/x", "../../x")
+ .relativize("/x", "../../../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/./a")
+ .relativize("/a", "")
+ .relativize("/", "..")
+ .relativize("/.", "..")
+ .relativize("/..", "..")
+ .relativize("/../..", "..")
+ .relativize("/a/b", "b")
+ .relativize("/a/b/c", "b/c")
+ .relativize("/a/.", "") // "." also valid
+ .relativize("/a/..", "..")
+ .relativize("/x", "../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/../a")
+ .relativize("/a", "")
+ .relativize("/", "..")
+ .relativize("/.", "..")
+ .relativize("/..", "..")
+ .relativize("/../..", "..")
+ .relativize("/a/b", "b")
+ .relativize("/a/b/c", "b/c")
+ .relativize("/a/.", "") // "." also valid
+ .relativize("/a/..", "..")
+ .relativize("/x", "../x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/a/..")
+ .relativize("/a", "a")
+ .relativize("/", "") // "." is also valid
+ .relativize("/.", "")
+ .relativize("/..", "")
+ .relativize("/../..", "")
+ .relativize("/a/.", "a")
+ .relativize("/a/..", "")
+ .relativize("/x", "x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("/")
+ .relativize("/a", "a")
+ .relativize("/", "") // "." is also valid
+ .relativize("/.", "")
+ .relativize("/..", "")
+ .relativize("/../..", "")
+ .relativize("/a/.", "a")
+ .relativize("/a/..", "")
+ .relativize("/x", "x")
+ .relativizeFail("x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("..");
+ test("a")
+ .relativize("a", "")
+ .relativize("", "..")
+ .relativize(".", "..")
+ .relativize("..", "../..")
+ .relativize("../..", "../../..")
+ .relativize("./..", "../..")
+ .relativize("a/b", "b")
+ .relativize("a/b/c", "b/c")
+ .relativize("../x", "../../x")
+ .relativizeFail("/")
+ .relativizeFail("/x");
+ test("a/b")
+ .relativize("a/b", "")
+ .relativize("a", "..")
+ .relativize("", "../..")
+ .relativize(".", "../..")
+ .relativize("..", "../../..")
+ .relativize("../..", "../../../..")
+ .relativize("./..", "../../..")
+ .relativize("a/b/c", "c")
+ .relativize("../x", "../../../x")
+ .relativizeFail("/")
+ .relativizeFail("/x");
test("a/b/c")
+ .relativize("a/b/c", "")
+ .relativize("a/b", "..")
+ .relativize("a", "../..")
+ .relativize("", "../../..")
+ .relativize(".", "../../..")
+ .relativize("..", "../../../..")
+ .relativize("../..", "../../../../..")
+ .relativize("./..", "../../../..")
.relativize("a/b/c/d", "d")
+ .relativize("a/b/c/d/e", "d/e")
.relativize("a/x", "../../x")
- .relativize("x", "../../../x")
- .relativize("", "../../..");
+ .relativize("../x", "../../../../x")
+ .relativizeFail("/")
+ .relativizeFail("/x");
test("")
.relativize("a", "a")
.relativize("a/b/c", "a/b/c")
- .relativize("", "");
+ .relativize("", "")
+ .relativize(".", ".")
+ .relativize("..", "..")
+ .relativize("../..", "../..")
+ .relativize("./..", "./..") // ".." also valid
+ .relativizeFail("/")
+ .relativizeFail("/x");
+ test("..")
+ .relativize("../a", "a")
+ .relativize("..", "")
+ .relativize("./..", "")
+ .relativizeFail("/")
+ .relativizeFail("/x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("x");
+ test("../a")
+ .relativize("../a/b", "b")
+ .relativize("../a", "")
+ .relativize("..", "..")
+ .relativize("./..", "..")
+ .relativizeFail("/")
+ .relativizeFail("/x")
+ .relativizeFail("")
+ .relativizeFail(".")
+ .relativizeFail("x");
+ test("../a/b")
+ .relativize("../a/b/c", "c")
+ .relativize("../a/b", "")
+ .relativize("../a", "..")
+ .relativize("..", "../..")
+ .relativize("./..", "../..")
+ .relativizeFail("/")
+ .relativizeFail("/x")
+ .relativizeFail("")
+ .relativizeFail("x");
+ test("a/..")
+ .relativize("b", "b")
+ .relativize("", "")
+ .relativize(".", "") // "." also valid
+ .relativize("..", "..")
+ .relativize("a/../b", "b")
+ .relativize("a/..", "")
+ .relativize("../b", "../b")
+ .relativize("b/..", "")
+ .relativizeFail("/")
+ .relativizeFail("/x");
+ test("a/../b")
+ .relativize("a/../b", "")
+ .relativize("a/..", "..")
+ .relativize("", "..")
+ .relativize(".", "..")
+ .relativize("..", "../..")
+ .relativize("b", "")
+ .relativize("c", "../c")
+ .relativize("../c", "../../c")
+ .relativize("a/../b/c", "c")
+ .relativizeFail("/")
+ .relativizeFail("/x");
// normalize
test("/")
--- a/jdk/test/java/nio/file/WatchService/LotsOfCancels.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/file/WatchService/LotsOfCancels.java Wed Jul 05 22:08:15 2017 +0200
@@ -53,10 +53,11 @@
Path testDir = Paths.get(System.getProperty("test.dir", "."));
Path top = Files.createTempDirectory(testDir, "LotsOfCancels");
for (int i=1; i<=16; i++) {
+ int id = i;
Path dir = Files.createDirectory(top.resolve("dir-" + i));
WatchService watcher = FileSystems.getDefault().newWatchService();
- pool.submit(() -> handle(dir, watcher));
- pool.submit(() -> poll(watcher));
+ pool.submit(() -> handle(id, dir, watcher));
+ pool.submit(() -> poll(id, watcher));
}
} finally {
pool.shutdown();
@@ -74,7 +75,8 @@
* Stress the given WatchService, specifically the cancel method, in
* the given directory. Closes the WatchService when done.
*/
- static void handle(Path dir, WatchService watcher) {
+ static void handle(int id, Path dir, WatchService watcher) {
+ System.out.printf("begin handle %d%n", id);
try {
try {
Path file = dir.resolve("anyfile");
@@ -85,12 +87,15 @@
key.cancel();
}
} finally {
+ System.out.printf("WatchService %d closing ...%n", id);
watcher.close();
+ System.out.printf("WatchService %d closed %n", id);
}
} catch (Exception e) {
e.printStackTrace();
failed = true;
}
+ System.out.printf("end handle %d%n", id);
}
/**
@@ -98,7 +103,8 @@
* queue drained, it also hogs a CPU core which seems necessary to
* tickle the original bug.
*/
- static void poll(WatchService watcher) {
+ static void poll(int id, WatchService watcher) {
+ System.out.printf("begin poll %d%n", id);
try {
for (;;) {
WatchKey key = watcher.take();
@@ -108,10 +114,12 @@
}
}
} catch (ClosedWatchServiceException expected) {
- // nothing to do
+ // nothing to do but print
+ System.out.printf("poll %d expected exception %s%n", id, expected);
} catch (Exception e) {
e.printStackTrace();
failed = true;
}
+ System.out.printf("end poll %d%n", id);
}
}
--- a/jdk/test/java/nio/file/WatchService/UpdateInterference.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/nio/file/WatchService/UpdateInterference.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,9 @@
import static java.nio.file.StandardWatchEventKinds.*;
public class UpdateInterference {
+
+ private static volatile boolean stop;
+
public static void main(String[] args) throws IOException, InterruptedException {
final Path root = Files.createTempDirectory("test");
final Path foo = root.resolve("foo");
@@ -43,64 +46,89 @@
Files.createDirectory(bar);
Files.createDirectory(baz);
- final WatchService watcher = root.getFileSystem().newWatchService();
- final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE);
- final WatchKey barKey = bar.register(watcher, ENTRY_CREATE);
+ try (final WatchService watcher = root.getFileSystem().newWatchService()) {
+ final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE);
+ final WatchKey barKey = bar.register(watcher, ENTRY_CREATE);
+
+ Thread t1 = null;
+ Thread t2 = null;
+ try {
+ t1 = new Thread() {
- new Thread() {
- { setDaemon(true); }
+ @Override
+ public void run() {
+ while (!stop) {
+ try {
+ final Path temp = Files.createTempFile(foo, "temp", ".tmp");
+ Files.delete(temp);
+ Thread.sleep(10);
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ };
+
+ t2 = new Thread() {
- @Override
- public void run() {
- while (true) {
- try {
- final Path temp = Files.createTempFile(foo, "temp", ".tmp");
- Files.delete(temp);
- Thread.sleep(10);
- } catch (IOException | InterruptedException e) {
- throw new RuntimeException(e);
+ @Override
+ public void run() {
+ WatchKey bazKeys[] = new WatchKey[32];
+ while (!stop) {
+ try {
+ for( int i = 0; i < bazKeys.length; i++) {
+ bazKeys[i] = baz.register(watcher, ENTRY_CREATE);
+ }
+ for( int i = 0; i < bazKeys.length; i++) {
+ bazKeys[i].cancel();
+ }
+ Thread.sleep(1);
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
+ };
+
+ t1.start();
+ t2.start();
+
+ long time = System.currentTimeMillis();
+ while ((System.currentTimeMillis() - time) < 15000) {
+ final WatchKey key = watcher.poll(60, TimeUnit.SECONDS);
+ if (key == null) continue;
+
+ if (key != fooKey) {
+ List<WatchEvent<?>> pollEvents = key.pollEvents();
+ for (WatchEvent<?> watchEvent : pollEvents) {
+ System.out.println(watchEvent.count() + " " +
+ watchEvent.kind() + " " +
+ watchEvent.context());
+ }
+ throw new RuntimeException("Event received for unexpected key");
+ }
+ key.reset();
+ }
+ } finally {
+ // the threads should stop before WatchService is closed
+ // to avoid ClosedWatchServiceException
+ stop = true;
+
+ // wait for threads to finish
+ if (t1 != null) {
+ t1.join();
+ }
+
+ if (t2 != null) {
+ t2.join();
}
}
- }.start();
-
- new Thread() {
- { setDaemon(true); }
-
- @Override
- public void run() {
- WatchKey bazKeys[] = new WatchKey[32];
- while (true) {
- try {
- for( int i = 0; i < bazKeys.length; i++) {
- bazKeys[i] = baz.register(watcher, ENTRY_CREATE);
- }
- for( int i = 0; i < bazKeys.length; i++) {
- bazKeys[i].cancel();
- }
- Thread.sleep(1);
- } catch (IOException | InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }.start();
-
- long time = System.currentTimeMillis();
- while ((System.currentTimeMillis() - time) < 15000) {
- final WatchKey key = watcher.poll(60, TimeUnit.SECONDS);
- if (key == null) continue;
-
- if (key != fooKey) {
- List<WatchEvent<?>> pollEvents = key.pollEvents();
- for (WatchEvent<?> watchEvent : pollEvents) {
- System.out.println(watchEvent.count() + " " +
- watchEvent.kind() + " " +
- watchEvent.context());
- }
- throw new RuntimeException("Event received for unexpected key");
- }
- key.reset();
+ } finally {
+ // clean up
+ Files.delete(foo);
+ Files.delete(bar);
+ Files.delete(baz);
+ Files.delete(root);
}
}
}
--- a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -419,6 +419,21 @@
ZoneOffset.ofHoursMinutesSeconds(-19, 0, 0);
}
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_factory_int_hours_minutes_seconds_minutesMinValue() {
+ ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, -1);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_factory_int_hours_minutes_seconds_secondsMinValue() {
+ ZoneOffset.ofHoursMinutesSeconds(0, 0, Integer.MIN_VALUE);
+ }
+
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_factory_int_hours_minutes_seconds_minutesAndSecondsMinValue() {
+ ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, Integer.MIN_VALUE);
+ }
+
//-----------------------------------------------------------------------
@Test
public void test_factory_ofTotalSeconds() {
@@ -437,6 +452,11 @@
ZoneOffset.ofTotalSeconds(-18 * 60 * 60 - 1);
}
+ @Test(expectedExceptions=DateTimeException.class)
+ public void test_factory_ofTotalSeconds_minValue() {
+ ZoneOffset.ofTotalSeconds(Integer.MIN_VALUE);
+ }
+
//-----------------------------------------------------------------------
// from()
//-----------------------------------------------------------------------
--- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -360,6 +360,21 @@
}
/**
+ * Test keySet().removeAll on empty map
+ */
+ public void testKeySet_empty_removeAll() {
+ ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
+ Set<Integer> set = map.keySet();
+ set.removeAll(Collections.emptyList());
+ assertTrue(map.isEmpty());
+ assertTrue(set.isEmpty());
+ // following is test for JDK-8163353
+ set.removeAll(Collections.emptySet());
+ assertTrue(map.isEmpty());
+ assertTrue(set.isEmpty());
+ }
+
+ /**
* keySet.toArray returns contains all keys
*/
public void testKeySetToArray() {
--- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java Wed Jul 05 22:08:15 2017 +0200
@@ -80,7 +80,7 @@
}
try (JarFile jf = new JarFile(multirelease)) {
- Assert.assertFalse(jf.isMultiRelease());
+ Assert.assertTrue(jf.isMultiRelease());
}
try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Runtime.version())) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8061842
+ * @summary Package jurisdiction policy files as something other than JAR
+ * @run main/othervm TestUnlimited "" exception
+ * @run main/othervm TestUnlimited limited fail
+ * @run main/othervm TestUnlimited unlimited pass
+ * @run main/othervm TestUnlimited unlimited/ pass
+ * @run main/othervm TestUnlimited NosuchDir exception
+ * @run main/othervm TestUnlimited . exception
+ * @run main/othervm TestUnlimited /tmp/unlimited exception
+ * @run main/othervm TestUnlimited ../policy/unlimited exception
+ * @run main/othervm TestUnlimited ./unlimited exception
+ * @run main/othervm TestUnlimited /unlimited exception
+ */
+import javax.crypto.*;
+import java.security.Security;
+
+public class TestUnlimited {
+
+ public static void main(String[] args) throws Exception {
+ /*
+ * Override the Security property to allow for unlimited policy.
+ * Would need appropriate permissions if Security Manager were
+ * active.
+ */
+ if (args.length != 2) {
+ throw new Exception("Two args required");
+ }
+
+ boolean expected = args[1].equals("pass");
+ boolean exception = args[1].equals("exception");
+ boolean result = false;
+
+ System.out.println("Testing: " + args[0]);
+
+ if (args[0].equals("\"\"")) {
+ Security.setProperty("crypto.policy", "");
+ } else {
+ Security.setProperty("crypto.policy", args[0]);
+ }
+
+ /*
+ * Use the AES as the test Cipher
+ * If there is an error initializing, we will never get past here.
+ */
+ try {
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
+ System.out.println("max AES key len:" + maxKeyLen);
+ if (maxKeyLen > 128) {
+ System.out.println("Unlimited policy is active");
+ result = true;
+ } else {
+ System.out.println("Unlimited policy is NOT active");
+ result = false;
+ }
+ } catch (Throwable e) {
+ if (!exception) {
+ throw new Exception();
+ }
+ }
+
+ System.out.println(
+ "Expected:\t" + expected + "\nResult:\t\t" + result);
+ if (expected != result) {
+ throw new Exception();
+ }
+
+ System.out.println("DONE!");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8151893
+ * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property
+ * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom
+ */
+
+import java.security.Security;
+import java.util.List;
+import org.jcp.xml.dsig.internal.dom.Policy;
+
+public class SecureValidationPolicy {
+
+ public static void main(String[] args) throws Exception {
+
+ List<String> restrictedSchemes = List.of("file:/tmp/foo",
+ "http://java.com", "https://java.com");
+ List<String> restrictedAlgs = List.of(
+ "http://www.w3.org/TR/1999/REC-xslt-19991116",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-md5",
+ "http://www.w3.org/2001/04/xmldsig-more#hmac-md5",
+ "http://www.w3.org/2001/04/xmldsig-more#md5");
+
+ // Test expected defaults
+ System.out.println("Testing defaults");
+ if (!Policy.restrictNumTransforms(6)) {
+ throw new Exception("maxTransforms not enforced");
+ }
+ if (!Policy.restrictNumReferences(31)) {
+ throw new Exception("maxReferences not enforced");
+ }
+ for (String scheme : restrictedSchemes) {
+ if (!Policy.restrictReferenceUriScheme(scheme)) {
+ throw new Exception(scheme + " scheme not restricted");
+ }
+ }
+ for (String alg : restrictedAlgs) {
+ if (!Policy.restrictAlg(alg)) {
+ throw new Exception(alg + " alg not restricted");
+ }
+ }
+ if (!Policy.restrictDuplicateIds()) {
+ throw new Exception("noDuplicateIds not enforced");
+ }
+ if (!Policy.restrictRetrievalMethodLoops()) {
+ throw new Exception("noRetrievalMethodLoops not enforced");
+ }
+ }
+}
--- a/jdk/test/jdk/lambda/TEST.properties Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/lambda/TEST.properties Wed Jul 05 22:08:15 2017 +0200
@@ -3,4 +3,4 @@
TestNG.dirs = .
javatest.maxOutputSize = 250000
-modules = jdk.compiler
+modules = jdk.compiler jdk.zipfs
--- a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
* @summary Verify the defining class loader of each module never delegates
* to its child class loader. Also sanity check java.compact2
* requires.
+ * @modules java.compact2
* @run testng/othervm --add-modules=ALL-SYSTEM VerifyModuleDelegation
*/
@@ -33,7 +34,9 @@
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
import java.util.Set;
+import static java.util.stream.Collectors.toSet;
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
@@ -58,8 +61,9 @@
.requires(Set.of(PUBLIC), "java.xml")
.build();
- private static final Set<ModuleReference> MREFS
- = ModuleFinder.ofSystem().findAll();
+ private static final Set<ModuleDescriptor> MREFS
+ = Layer.boot().modules().stream().map(Module::getDescriptor)
+ .collect(toSet());
private void check(ModuleDescriptor md, ModuleDescriptor ref) {
assertTrue(md.requires().size() == ref.requires().size());
@@ -69,7 +73,7 @@
@Test
public void checkJavaBase() {
ModuleDescriptor md =
- MREFS.stream().map(ModuleReference::descriptor)
+ MREFS.stream()
.filter(d -> d.name().equals(JAVA_BASE))
.findFirst().orElseThrow(Error::new);
@@ -78,7 +82,7 @@
@Test
public void checkCompact2() {
ModuleDescriptor md =
- MREFS.stream().map(ModuleReference::descriptor)
+ MREFS.stream()
.filter(d -> d.name().equals(JAVA_COMPACT2))
.findFirst().orElseThrow(Error::new);
check(md, COMPACT2);
@@ -87,7 +91,7 @@
@Test
public void checkLoaderDelegation() {
Layer boot = Layer.boot();
- MREFS.stream().map(ModuleReference::descriptor)
+ MREFS.stream()
.forEach(md -> md.requires().stream().forEach(req ->
{
// check if M requires D and D's loader must be either the
--- a/jdk/test/jdk/modules/scenarios/container/ContainerTest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/modules/scenarios/container/ContainerTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -26,6 +26,8 @@
* @library /lib/testlibrary
* @modules jdk.jartool/sun.tools.jar
* jdk.compiler
+ * jdk.zipfs
+ * java.se
* @build ContainerTest CompilerUtils jdk.testlibrary.*
* @run testng ContainerTest
* @summary Starts a simple container that uses dynamic configurations
--- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -28,7 +28,7 @@
* @library /lib/testlibrary/java/util/jar
* @build Compiler JarBuilder CreateMultiReleaseTestJars
* @run testng MultiReleaseJarTest
- * @modules java.compiler
+ * @modules jdk.compiler
* jdk.jartool
* jdk.zipfs
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8164389
+ * @summary walk entries in a jdk.nio.zipfs.JarFileSystem
+ * @modules jdk.jartool/sun.tools.jar
+ * @run testng JFSTester
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class JFSTester {
+ private URI jarURI;
+ private Path jarfile;
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ String userdir = System.getProperty("user.dir",".");
+ jarfile = Paths.get(userdir, "test.jar");
+ String srcdir = System.getProperty("test.src");
+ String[] args = (
+ "-cf "
+ + jarfile.toString()
+ + " -C "
+ + srcdir
+ + " root --release 9 -C "
+ + srcdir
+ + System.getProperty("file.separator")
+ + "v9 root"
+ ).split(" +");
+ new sun.tools.jar.Main(System.out, System.err, "jar").run(args);
+ String ssp = jarfile.toUri().toString();
+ jarURI = new URI("jar", ssp, null);
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ Files.deleteIfExists(jarfile);
+ }
+
+ @Test
+ public void testWalk() throws IOException {
+
+ // no configuration, treat multi-release jar as unversioned
+ Map<String,String> env = new HashMap<>();
+ Set<String> contents = doTest(env);
+ Set<String> baseContents = Set.of(
+ "This is leaf 1.\n",
+ "This is leaf 2.\n",
+ "This is leaf 3.\n",
+ "This is leaf 4.\n"
+ );
+ Assert.assertEquals(contents, baseContents);
+
+ // a configuration and jar file is multi-release
+ env.put("multi-release", "9");
+ contents = doTest(env);
+ Set<String> versionedContents = Set.of(
+ "This is versioned leaf 1.\n",
+ "This is versioned leaf 2.\n",
+ "This is versioned leaf 3.\n",
+ "This is versioned leaf 4.\n"
+ );
+ Assert.assertEquals(contents, versionedContents);
+ }
+
+ private Set<String> doTest(Map<String,String> env) throws IOException {
+ Set<String> contents;
+ try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) {
+ Path root = fs.getPath("root");
+ contents = Files.walk(root)
+ .filter(p -> !Files.isDirectory(p))
+ .map(this::pathToContents)
+ .collect(Collectors.toSet());
+ }
+ return contents;
+ }
+
+ private String pathToContents(Path path) {
+ try {
+ return new String(Files.readAllBytes(path));
+ } catch (IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is leaf 1.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is leaf 2.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is leaf 3.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is leaf 4.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is versioned leaf 1.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is versioned leaf 2.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is versioned leaf 3.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,1 @@
+This is versioned leaf 4.
--- a/jdk/test/jdk/security/JavaDotSecurity/final_java_security Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/security/JavaDotSecurity/final_java_security Wed Jul 05 22:08:15 2017 +0200
@@ -10,6 +10,7 @@
foo.6=9a
foo.7=10
foo.8=12
+crypto.policy=somepolicy
package.access=sun.,\
solaris.,\
--- a/jdk/test/jdk/security/JavaDotSecurity/ifdefs.sh Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/security/JavaDotSecurity/ifdefs.sh Wed Jul 05 22:08:15 2017 +0200
@@ -46,7 +46,13 @@
fi
$JAVAC -d . $TOOLSRC
-$JAVA $TOOLNAME $TESTSRC/raw_java_security outfile solaris sparc $TESTSRC/more_restricted
+$JAVA $TOOLNAME \
+ $TESTSRC/raw_java_security \
+ outfile \
+ solaris \
+ sparc \
+ somepolicy \
+ $TESTSRC/more_restricted
# On Windows, line end could be different. -b is a cross-platform option.
-diff -b outfile $TESTSRC/final_java_security
\ No newline at end of file
+diff -b outfile $TESTSRC/final_java_security
--- a/jdk/test/jdk/security/JavaDotSecurity/raw_java_security Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/security/JavaDotSecurity/raw_java_security Wed Jul 05 22:08:15 2017 +0200
@@ -44,6 +44,7 @@
#ifndef macosx-x64
foo.tbd=12
#endif
+crypto.policy=crypto.policydir-tbd
package.access=sun.,\
#ifdef solaris
--- a/jdk/test/jdk/security/jarsigner/Spec.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/jdk/security/jarsigner/Spec.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
* @modules java.base/sun.security.tools.keytool
* java.base/sun.security.provider.certpath
* jdk.jartool
+ * jdk.crypto.ec
*/
import com.sun.jarsigner.ContentSigner;
--- a/jdk/test/sun/security/krb5/auto/BadKdc1.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java Wed Jul 05 22:08:15 2017 +0200
@@ -44,16 +44,16 @@
}
BadKdc.go(
- "121212222222(32){1,2}1222(32){1,2}", // 1 2
+ "121212222222(32){1,3}1222(32){1,3}", // 1 2
// The above line means try kdc1 for 2 seconds then kdc1
// for 2 seconds... finally kdc3 for 2 seconds.
- "1222(32){1,2}1222(32){1,2}", // 1 2
+ "1222(32){1,3}1222(32){1,3}", // 1 2
// refresh
- "121212222222(32){1,2}1222(32){1,2}", // 1 2
+ "121212222222(32){1,3}1222(32){1,3}", // 1 2
// k3 off k2 on
- "(122212(22){1,2}|1222323232-)", // 1
+ "(122212(22){1,3}|1222323232-)", // 1
// k1 on
- "(12(12){1,2}|122212|122232-)" // empty
+ "(12(12){1,3}|122212|122232-)" // empty
);
}
}
--- a/jdk/test/sun/security/krb5/auto/BadKdc2.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java Wed Jul 05 22:08:15 2017 +0200
@@ -42,14 +42,14 @@
Security.setProperty(
"krb5.kdc.bad.policy", "tryLess:2," + BadKdc.toReal(1000));
BadKdc.go(
- "121212222222(32){1,2}11112121(32){1,2}", // 1 2
- "11112121(32){1,2}11112121(32){1,2}", // 1 2
+ "121212222222(32){1,3}11112121(32){1,3}", // 1 2
+ "11112121(32){1,3}11112121(32){1,3}", // 1 2
// refresh
- "121212222222(32){1,2}11112121(32){1,2}", // 1 2
+ "121212222222(32){1,3}11112121(32){1,3}", // 1 2
// k3 off k2 on
- "1111(21){1,2}1111(22){1,2}", // 1
+ "1111(21){1,3}1111(22){1,3}", // 1
// k1 on
- "(11){1,2}(12){1,2}" // empty
+ "(11){1,3}(12){1,3}" // empty
);
}
}
--- a/jdk/test/sun/security/krb5/auto/BadKdc4.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/sun/security/krb5/auto/BadKdc4.java Wed Jul 05 22:08:15 2017 +0200
@@ -37,12 +37,12 @@
throws Exception {
Security.setProperty("krb5.kdc.bad.policy", "");
BadKdc.go(
- "121212222222(32){1,2}121212222222(32){1,2}",
- "121212222222(32){1,2}121212222222(32){1,2}",
+ "121212222222(32){1,3}121212222222(32){1,3}",
+ "121212222222(32){1,3}121212222222(32){1,3}",
// refresh
- "121212222222(32){1,2}121212222222(32){1,2}",
+ "121212222222(32){1,3}121212222222(32){1,3}",
// k3 off k2 on
- "121212(22){1,2}121212(22){1,2}",
+ "121212(22){1,3}121212(22){1,3}",
// k1 on
"(12){2,4}"
);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/KdcPolicy.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.security.auth.login.LoginException;
+import sun.security.krb5.Asn1Exception;
+import sun.security.krb5.Config;
+
+/*
+ * @test
+ * @bug 8164656
+ * @run main/othervm KdcPolicy udp
+ * @run main/othervm KdcPolicy tcp
+ * @summary krb5.kdc.bad.policy test
+ */
+public class KdcPolicy {
+
+ // Is this test on UDP?
+ static boolean udp;
+
+ public static void main(String[] args) throws Exception {
+
+ udp = args[0].equals("udp");
+
+ try {
+ main0();
+ } catch (LoginException le) {
+ Throwable cause = le.getCause();
+ if (cause instanceof Asn1Exception) {
+ System.out.println("Another process sends a packet to " +
+ "this server. Ignored.");
+ return;
+ }
+ throw le;
+ }
+ }
+
+ static DebugMatcher cm = new DebugMatcher();
+
+ static void main0() throws Exception {
+
+ System.setProperty("sun.security.krb5.debug", "true");
+
+ // One real KDC. Must be created before fake KDCs
+ // to read the TestHosts file.
+ OneKDC kdc = new OneKDC(null);
+
+ // Two fake KDCs, d1 and d2 only listen but do not respond.
+
+ if (udp) {
+ try (DatagramSocket d1 = new DatagramSocket();
+ DatagramSocket d2 = new DatagramSocket()) {
+ run(d1.getLocalPort(), d2.getLocalPort(), kdc.getPort());
+ }
+ } else {
+ try (ServerSocket d1 = new ServerSocket(0);
+ ServerSocket d2 = new ServerSocket(0)) {
+ run(d1.getLocalPort(), d2.getLocalPort(), kdc.getPort());
+ }
+ }
+ }
+
+ static void run(int p1, int p2, int p3) throws Exception {
+
+ // cm.kdc() will return a and b for fake KDCs, and c for real KDC.
+ cm.addPort(-1).addPort(p1).addPort(p2).addPort(p3);
+
+ System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
+
+ // Check default timeout is 30s. Use real KDC only, otherwise too
+ // slow to wait for timeout.
+ writeConf(-1, -1, p3);
+ test("c30000c30000");
+
+ // 1. Default policy is tryLast
+ //Security.setProperty("krb5.kdc.bad.policy", "tryLast");
+
+ // Need a real KDC, otherwise there is no last good.
+ // This test waste 3 seconds waiting for d1 to timeout.
+ // It is possible the real KDC cannot fulfil the request
+ // in 3s, so it might fail (either 1st time or 2nd time).
+ writeConf(1, 3000, p1, p3);
+ test("a3000c3000c3000|a3000c3000-|a3000c3000c3000-");
+
+ // If a test case won't use a real KDC, it can be sped up.
+ writeConf(3, 5, p1, p2);
+ test("a5a5a5b5b5b5-"); // default max_retries == 3
+ test("a5a5a5b5b5b5-"); // all bad means no bad
+
+ // 2. No policy.
+ Security.setProperty("krb5.kdc.bad.policy", "");
+ Config.refresh();
+
+ // This case needs a real KDC, otherwise, all bad means no
+ // bad and we cannot tell the difference. This case waste 3
+ // seconds on d1 to timeout twice. It is possible the real KDC
+ // cannot fulfil the request within 3s, so it might fail
+ // (either 1st time or 2nd time).
+ writeConf(1, 3000, p1, p3);
+ test("a3000c3000a3000c3000|a3000c3000-|a3000c3000a3000c3000-");
+
+ // 3. tryLess with no argument means tryLess:1,5000
+ Security.setProperty("krb5.kdc.bad.policy", "tryLess");
+
+ // This case will waste 11s. We are checking that the default
+ // value of 5000 in tryLess is only used if it's less than timeout
+ // in krb5.conf
+ writeConf(1, 6000, p1);
+ test("a6000-"); // timeout in krb5.conf is 6s
+ test("a5000-"); // tryLess to 5s. This line can be made faster if
+ // d1 is a read KDC, but we have no existing method
+ // to start KDC on an existing ServerSocket (port).
+
+ writeConf(-1, 4, p1, p2);
+ test("a4a4a4b4b4b4-"); // default max_retries == 3
+ test("a4b4-"); // tryLess to 1. And since 4 < 5000, use 4.
+ Config.refresh();
+ test("a4a4a4b4b4b4-");
+
+ writeConf(5, 4, p1, p2);
+ test("a4a4a4a4a4b4b4b4b4b4-"); // user-provided max_retries == 5
+ test("a4b4-");
+ Config.refresh();
+ test("a4a4a4a4a4b4b4b4b4b4-");
+
+ // 3. tryLess with arguments
+ Security.setProperty("krb5.kdc.bad.policy",
+ "tryLess:2,5");
+
+ writeConf(-1, 6, p1, p2);
+ test("a6a6a6b6b6b6-"); // default max_retries == 3
+ test("a5a5b5b5-"); // tryLess to 2
+ Config.refresh();
+ test("a6a6a6b6b6b6-");
+
+ writeConf(5, 4, p1, p2);
+ test("a4a4a4a4a4b4b4b4b4b4-"); // user-provided max_retries == 5
+ test("a4a4b4b4-"); // tryLess to 2
+ Config.refresh();
+ test("a4a4a4a4a4b4b4b4b4b4-");
+ }
+
+ /**
+ * Writes a krb5.conf file.
+ * @param max max_retries, -1 if not set
+ * @param to kdc_timeout, -1 if not set
+ * @param ports where KDCs listen on
+ */
+ static void writeConf(int max, int to, int... ports) throws Exception {
+
+ // content of krb5.conf
+ String conf = "";
+
+ // Extra settings in [libdefaults]
+ String inDefaults = "";
+
+ // Extra settings in [realms]
+ String inRealm = "";
+
+ // We will randomly put extra settings only in [libdefaults],
+ // or in [realms] but with different values in [libdefaults],
+ // to prove that settings in [realms] override those in [libdefaults].
+ Random r = new Random();
+
+ if (max > 0) {
+ if (r.nextBoolean()) {
+ inDefaults += "max_retries = " + max + "\n";
+ } else {
+ inRealm += " max_retries = " + max + "\n";
+ inDefaults += "max_retries = " + (max + 1) + "\n";
+ }
+ }
+
+ if (to > 0) {
+ if (r.nextBoolean()) {
+ inDefaults += "kdc_timeout = " + to + "\n";
+ } else {
+ inRealm += " kdc_timeout = " + to + "\n";
+ inDefaults += "kdc_timeout = " + (to + 1) + "\n";
+ }
+ }
+
+ if (udp) {
+ if (r.nextBoolean()) {
+ inDefaults += "udp_preference_limit = 10000\n";
+ } else if (r.nextBoolean()) {
+ inRealm += " udp_preference_limit = 10000\n";
+ inDefaults += "udp_preference_limit = 1\n";
+ } // else no settings means UDP
+ } else {
+ if (r.nextBoolean()) {
+ inDefaults += "udp_preference_limit = 1\n";
+ } else {
+ inRealm += " udp_preference_limit = 1\n";
+ inDefaults += "udp_preference_limit = 10000\n";
+ }
+ }
+
+ conf = "[libdefaults]\n" +
+ "default_realm = " + OneKDC.REALM + "\n" +
+ inDefaults +
+ "\n" +
+ "[realms]\n" +
+ OneKDC.REALM + " = {\n";
+
+ for (int port : ports) {
+ conf += " kdc = " + OneKDC.KDCHOST + ":" + port + "\n" +
+ inRealm;
+ }
+
+ conf += "}\n";
+
+ Files.write(Paths.get("alternative-krb5.conf"), conf.getBytes());
+ Config.refresh();
+ }
+
+ /**
+ * One call of krb5 login. As long as the result matches one of expected,
+ * the test is considered as success. The grammar of expected is
+ *
+ * kdc#, timeout, kdc#, timeout, ..., optional "-" for failure
+ */
+ static void test(String... expected) throws Exception {
+
+ System.out.println("------------------TEST----------------------");
+ PrintStream oldOut = System.out;
+ boolean failed = false;
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(bo));
+ try {
+ Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+ } catch (Exception e) {
+ failed = true;
+ } finally {
+ System.setOut(oldOut);
+ }
+
+ String[] lines = new String(bo.toByteArray()).split("\n");
+ StringBuilder sb = new StringBuilder();
+ for (String line: lines) {
+ if (cm.match(line)) {
+ if (udp != cm.isUDP()) {
+ sb.append("x");
+ }
+ sb.append(cm.kdc()).append(cm.timeout());
+ }
+ }
+ if (failed) sb.append('-');
+
+ String output = sb.toString();
+
+ boolean found = false;
+ for (String ex : expected) {
+ if (output.matches(ex)) {
+ System.out.println("Expected: " + ex + ", actual " + output);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ System.out.println("--------------- ERROR START -------------");
+ System.out.println(new String(bo.toByteArray()));
+ System.out.println("--------------- ERROR END ---------------");
+ throw new Exception("Does not match. Output is " + output);
+ }
+ }
+
+ /**
+ * A helper class to match the krb5 debug output:
+ * >>> KDCCommunication: kdc=host UDP:11555, timeout=200,Attempt =1, #bytes=138
+ *
+ * Example:
+ * DebugMatcher cm = new DebugMatcher();
+ * cm.addPort(12345).addPort(11555);
+ * for (String line : debugOutput) {
+ * if (cm.match(line)) {
+ * System.out.printf("%c%d\n", cm.kdc(), cm.timeout());
+ * // shows b200 for the example above
+ * }
+ * }
+ */
+ static class DebugMatcher {
+
+ static final Pattern re = Pattern.compile(
+ ">>> KDCCommunication: kdc=\\S+ (TCP|UDP):(\\d+), " +
+ "timeout=(\\d+),Attempt\\s*=(\\d+)");
+
+ List<Integer> kdcPorts = new ArrayList<>();
+ Matcher matcher;
+
+ /**
+ * Add KDC ports one by one. See {@link #kdc()}.
+ */
+ DebugMatcher addPort(int port) {
+ if (port > 0) {
+ kdcPorts.add(port);
+ } else {
+ kdcPorts.clear();
+ }
+ return this;
+ }
+
+ /**
+ * When a line matches the ">>> KDCCommunication:" pattern. After a
+ * match, the getters below can be called on this match.
+ */
+ boolean match(String line) {
+ matcher = re.matcher(line);
+ return matcher.find();
+ }
+
+ /**
+ * Protocol of this match, "UDP" or "TCP".
+ */
+ boolean isUDP() {
+ return matcher.group(1).equals("UDP");
+ }
+
+ /**
+ * KDC for this match, "a" for the one 1st added bt addPort(), "b"
+ * for second, etc. Undefined for not added.
+ */
+ char kdc() {
+ int port = Integer.parseInt(matcher.group(2));
+ return (char) (kdcPorts.indexOf(port) + 'a');
+ }
+
+ /**
+ * Timeout value for this match.
+ */
+ int timeout() {
+ return Integer.parseInt(matcher.group(3));
+ }
+ }
+}
--- a/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java Wed Jul 05 22:08:15 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,67 +26,96 @@
* @bug 4674913
* @summary Verify that EOFException are correctly handled during the handshake
* @author Andreas Sterbenz
+ * @run main/othervm CloseSocket
*/
-import java.io.*;
-import java.net.*;
-
-import javax.net.ssl.*;
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
public class CloseSocket {
+ private static ArrayList<TestCase> testCases = new ArrayList<>();
+
+ static {
+ testCases.add(socket -> socket.startHandshake());
+ testCases.add(socket -> {
+ InputStream in = socket.getInputStream();
+ in.read();
+ });
+ testCases.add(socket -> {
+ OutputStream out = socket.getOutputStream();
+ out.write(43);
+ });
+ }
+
public static void main(String[] args) throws Exception {
- final ServerSocket serverSocket = new ServerSocket(0);
- int serverPort = serverSocket.getLocalPort();
- new Thread() {
- public void run() {
- try {
- Socket s = serverSocket.accept();
- System.out.println("Server accepted connection");
- // wait a bit before closing the socket to give
- // the client time to send its hello message
- Thread.currentThread().sleep(100);
- s.close();
- System.out.println("Server closed socket, done.");
- } catch (Exception e) {
- System.out.println("Server exception:");
- e.printStackTrace();
+ try (Server server = new Server()) {
+ new Thread(server).start();
+
+ SocketFactory factory = SSLSocketFactory.getDefault();
+ try (SSLSocket socket = (SSLSocket) factory.createSocket("localhost",
+ server.getPort())) {
+ socket.setSoTimeout(2000);
+ System.out.println("Client established TCP connection");
+ boolean failed = false;
+ for (TestCase testCase : testCases) {
+ try {
+ testCase.test(socket);
+ System.out.println("ERROR: no exception");
+ failed = true;
+ } catch (IOException e) {
+ System.out.println("Failed as expected: " + e);
+ }
+ }
+ if (failed) {
+ throw new Exception("One or more tests failed");
}
}
- }.start();
- SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
- SSLSocket socket = (SSLSocket)factory.createSocket("localhost", serverPort);
- System.out.println("Client established TCP connection");
- boolean failed = false;
- try {
- System.out.println("Starting handshake...");
- socket.startHandshake();
- System.out.println("ERROR: no exception");
- failed = true;
- } catch (IOException e) {
- System.out.println("Failed as expected: " + e);
- }
- try {
- System.out.println("Trying read...");
- InputStream in = socket.getInputStream();
- int b = in.read();
- System.out.println("ERROR: no exception, read: " + b);
- failed = true;
- } catch (IOException e) {
- System.out.println("Failed as expected: " + e);
- }
- try {
- System.out.println("Trying read...");
- OutputStream out = socket.getOutputStream();
- out.write(43);
- System.out.println("ERROR: no exception");
- failed = true;
- } catch (IOException e) {
- System.out.println("Failed as expected: " + e);
- }
- if (failed) {
- throw new Exception("One or more tests failed");
}
}
+ static class Server implements AutoCloseable, Runnable {
+
+ final ServerSocket serverSocket;
+
+ Server() throws IOException {
+ serverSocket = new ServerSocket(0);
+ }
+
+ public int getPort() {
+ return serverSocket.getLocalPort();
+ }
+
+ @Override
+ public void run() {
+ try (Socket s = serverSocket.accept()) {
+ System.out.println("Server accepted connection");
+ // wait a bit before closing the socket to give
+ // the client time to send its hello message
+ Thread.currentThread().sleep(100);
+ s.close();
+ System.out.println("Server closed socket, done.");
+ } catch (Exception e) {
+ throw new RuntimeException("Problem in test execution", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (!serverSocket.isClosed()) {
+ serverSocket.close();
+ }
+ }
+ }
+
+ interface TestCase {
+ void test(SSLSocket socket) throws IOException;
+ }
}
--- a/jdk/test/tools/jlink/CustomPluginTest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/tools/jlink/CustomPluginTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -67,6 +67,7 @@
testHelloProvider(helper, pluginModulePath);
testCustomPlugins(helper, pluginModulePath);
+ testModuleVerification(helper, pluginModulePath);
}
private void testCustomPlugins(Helper helper, Path pluginModulePath) {
@@ -93,8 +94,7 @@
String name = "customplugin";
Path src = Paths.get(System.getProperty("test.src")).resolve(name);
Path classes = helper.getJmodClassesDir().resolve(name);
- JImageGenerator.compile(src, classes,
- "--add-exports", "jdk.jlink/jdk.tools.jlink.internal=customplugin");
+ JImageGenerator.compile(src, classes);
return JImageGenerator.getJModTask()
.addClassPath(classes)
.jmod(helper.getJmodDir().resolve(name + ".jmod"))
@@ -136,4 +136,44 @@
throw new AssertionError("Custom plugin not called");
}
}
+
+ private void testModuleVerification(Helper helper, Path pluginModulePath) throws IOException {
+ {
+ // dependent module missing check
+ String moduleName = "bar"; // 8147491
+ Path jmodFoo = helper.generateDefaultJModule("foo").assertSuccess();
+ Path jmodBar = helper.generateDefaultJModule(moduleName, "foo").assertSuccess();
+ // rogue filter removes "foo" module resources which are
+ // required by "bar" module. Module checks after plugin
+ // application should detect and report error.
+ JImageGenerator.getJLinkTask()
+ .modulePath(helper.defaultModulePath())
+ .pluginModulePath(pluginModulePath)
+ .output(helper.createNewImageDir(moduleName))
+ .addMods(moduleName)
+ .option("--rogue-filter")
+ .option("/foo/")
+ .call()
+ .assertFailure("java.lang.module.ResolutionException");
+ }
+
+ {
+ // package exported by one module used as concealed package
+ // in another module. But, module-info.class is not updated!
+ String moduleName = "jdk.scripting.nashorn";
+ JImageGenerator.getJLinkTask()
+ .modulePath(helper.defaultModulePath())
+ .pluginModulePath(pluginModulePath)
+ .output(helper.createNewImageDir(moduleName))
+ .addMods(moduleName)
+ // "java.logging" includes a package 'javax.script'
+ // which is an exported package from "java.scripting" module!
+ // module-info.class of java.logging left "as is".
+ .option("--rogue-adder")
+ .option("/java.logging/javax/script/Foo.class")
+ .call()
+ .assertFailure(
+ "Module java.logging's descriptor returns inconsistent package set");
+ }
+ }
}
--- a/jdk/test/tools/jlink/ImageFileCreatorTest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -220,7 +220,7 @@
};
ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
- null);
+ null, false);
ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
}
--- a/jdk/test/tools/jlink/customplugin/module-info.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/tools/jlink/customplugin/module-info.java Wed Jul 05 22:08:15 2017 +0200
@@ -25,4 +25,6 @@
requires jdk.jlink;
provides jdk.tools.jlink.plugin.Plugin with plugin.HelloPlugin;
provides jdk.tools.jlink.plugin.Plugin with plugin.CustomPlugin;
+ provides jdk.tools.jlink.plugin.Plugin with plugin.RogueAdderPlugin;
+ provides jdk.tools.jlink.plugin.Plugin with plugin.RogueFilterPlugin;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/customplugin/plugin/RogueAdderPlugin.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.Function;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
+import jdk.tools.jlink.plugin.Plugin;
+
+/**
+ * Rogue adder plugin
+ */
+public final class RogueAdderPlugin implements Plugin {
+ public static final String NAME = "rogue-adder";
+ private String resName;
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
+ in.transformAndCopy(Function.identity(), out);
+ out.add(ResourcePoolEntry.create(resName, new byte[1]));
+ return out.build();
+ }
+
+ @Override
+ public String getDescription() {
+ return NAME + "-description";
+ }
+
+ @Override
+ public Category getType() {
+ return Category.FILTER;
+ }
+
+ @Override
+ public boolean hasArguments() {
+ return true;
+ }
+
+ @Override
+ public void configure(Map<String, String> config) {
+ resName = config.get(NAME);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/customplugin/plugin/RogueFilterPlugin.java Wed Jul 05 22:08:15 2017 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.Map;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.Plugin;
+
+/**
+ * Rogue filter plugin
+ */
+public final class RogueFilterPlugin implements Plugin {
+ public static final String NAME = "rogue-filter";
+ private String prefix;
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
+ in.transformAndCopy((file) -> {
+ return file.path().startsWith(prefix)? null : file;
+ }, out);
+ return out.build();
+ }
+
+ @Override
+ public String getDescription() {
+ return NAME + "-description";
+ }
+
+ @Override
+ public Category getType() {
+ return Category.FILTER;
+ }
+
+ @Override
+ public boolean hasArguments() {
+ return true;
+ }
+
+ @Override
+ public void configure(Map<String, String> config) {
+ prefix = config.get(NAME);
+ }
+}
--- a/jdk/test/tools/jlink/plugins/GenerateJLIClassesPluginTest.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/GenerateJLIClassesPluginTest.java Wed Jul 05 22:08:15 2017 +0200
@@ -73,47 +73,6 @@
classFilesForSpecies(GenerateJLIClassesPlugin.defaultSpecies()),
List.of());
-
- // Test a valid set of options
- result = JImageGenerator.getJLinkTask()
- .modulePath(helper.defaultModulePath())
- .output(helper.createNewImageDir("generate-jli"))
- .option("--generate-jli-classes=bmh:bmh-species=LL,L3")
- .addMods("java.base")
- .call();
-
- image = result.assertSuccess();
-
- JImageValidator.validate(
- image.resolve("lib").resolve("modules"),
- classFilesForSpecies(List.of("LL", "L3")),
- classFilesForSpecies(List.of("L4")));
-
-
- // Test disabling BMH species generation
- result = JImageGenerator.getJLinkTask()
- .modulePath(helper.defaultModulePath())
- .output(helper.createNewImageDir("generate-jli"))
- .option("--generate-jli-classes=not-bmh:bmh-species=LL,L3")
- .addMods("java.base")
- .call();
-
- image = result.assertSuccess();
- JImageValidator.validate(
- image.resolve("lib").resolve("modules"),
- List.of(),
- classFilesForSpecies(List.of("LL", "L3", "L4")));
-
-
- // Test an invalid set of options
- result = JImageGenerator.getJLinkTask()
- .modulePath(helper.defaultModulePath())
- .output(helper.createNewImageDir("generate-jli"))
- .option("--generate-jli-classes=bmh:bmh-species=LL,L7V")
- .addMods("java.base")
- .call();
-
- result.assertFailure();
}
private static List<String> classFilesForSpecies(List<String> species) {
--- a/jdk/test/tools/launcher/VersionCheck.java Thu Aug 25 21:18:44 2016 +0000
+++ b/jdk/test/tools/launcher/VersionCheck.java Wed Jul 05 22:08:15 2017 +0200
@@ -82,6 +82,7 @@
"jcmd",
"jconsole",
"jcontrol",
+ "jdeprscan",
"jdeps",
"jimage",
"jinfo",