--- a/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -358,3 +358,4 @@
6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113
c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114
8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115
+84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116
--- a/.hgtags-top-repo Fri May 06 11:47:45 2016 +0300
+++ b/.hgtags-top-repo Fri May 06 06:23:30 2016 -0700
@@ -358,3 +358,4 @@
55b6d550828d1223b364e6ead4a56e56411c56df jdk-9+113
1d992540870ff33fe6cc550443388588df9b9e4f jdk-9+114
09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115
+6743a8e0cab7b5f6f4a0575f6664892f0ab740af jdk-9+116
--- a/common/autoconf/boot-jdk.m4 Fri May 06 11:47:45 2016 +0300
+++ b/common/autoconf/boot-jdk.m4 Fri May 06 06:23:30 2016 -0700
@@ -397,6 +397,7 @@
ADD_JVM_ARG_IF_OK([-XX:+UseSerialGC],boot_jdk_jvmargs_small,[$JAVA])
ADD_JVM_ARG_IF_OK([-Xms32M],boot_jdk_jvmargs_small,[$JAVA])
ADD_JVM_ARG_IF_OK([-Xmx512M],boot_jdk_jvmargs_small,[$JAVA])
+ ADD_JVM_ARG_IF_OK([-XX:TieredStopAtLevel=1],boot_jdk_jvmargs_small,[$JAVA])
AC_MSG_RESULT([$boot_jdk_jvmargs_small])
--- a/common/autoconf/compare.sh.in Fri May 06 11:47:45 2016 +0300
+++ b/common/autoconf/compare.sh.in Fri May 06 06:23:30 2016 -0700
@@ -31,7 +31,7 @@
export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@
-sexport OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
+export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@"
export OPENJDK_TARGET_CPU_LIBDIR="@OPENJDK_TARGET_CPU_LIBDIR@"
export DEBUG_LEVEL="@DEBUG_LEVEL@"
--- a/common/autoconf/generated-configure.sh Fri May 06 11:47:45 2016 +0300
+++ b/common/autoconf/generated-configure.sh Fri May 06 06:23:30 2016 -0700
@@ -1224,9 +1224,9 @@
with_dxsdk
with_dxsdk_lib
with_dxsdk_include
-enable_jtreg_failure_handler
enable_new_hotspot_build
enable_hotspot_test_in_build
+enable_jtreg_failure_handler
with_num_cores
with_memory_size
with_jobs
@@ -5070,7 +5070,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1460963400
+DATE_WHEN_GENERATED=1462204427
###############################################################################
#
@@ -15492,7 +15492,7 @@
HOTSPOT_TARGET_CPU_DEFINE=PPC32
elif test "x$OPENJDK_TARGET_CPU" = xs390; then
HOTSPOT_TARGET_CPU_DEFINE=S390
- elif test "x$OPENJDK_TARGET_CPU" = ss390x; then
+ elif test "x$OPENJDK_TARGET_CPU" = xs390x; then
HOTSPOT_TARGET_CPU_DEFINE=S390
fi
@@ -15648,7 +15648,7 @@
HOTSPOT_BUILD_CPU_DEFINE=PPC32
elif test "x$OPENJDK_BUILD_CPU" = xs390; then
HOTSPOT_BUILD_CPU_DEFINE=S390
- elif test "x$OPENJDK_BUILD_CPU" = ss390x; then
+ elif test "x$OPENJDK_BUILD_CPU" = xs390x; then
HOTSPOT_BUILD_CPU_DEFINE=S390
fi
@@ -64282,6 +64282,21 @@
fi
+ $ECHO "Check if jvm arg is ok: -XX:TieredStopAtLevel=1" >&5
+ $ECHO "Command: $JAVA -XX:TieredStopAtLevel=1 -version" >&5
+ OUTPUT=`$JAVA -XX:TieredStopAtLevel=1 -version 2>&1`
+ FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn`
+ FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""`
+ if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+ boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:TieredStopAtLevel=1"
+ JVM_ARG_OK=true
+ else
+ $ECHO "Arg failed:" >&5
+ $ECHO "$OUTPUT" >&5
+ JVM_ARG_OK=false
+ fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5
$as_echo "$boot_jdk_jvmargs_small" >&6; }
--- a/common/autoconf/platform.m4 Fri May 06 11:47:45 2016 +0300
+++ b/common/autoconf/platform.m4 Fri May 06 06:23:30 2016 -0700
@@ -435,7 +435,7 @@
HOTSPOT_$1_CPU_DEFINE=PPC32
elif test "x$OPENJDK_$1_CPU" = xs390; then
HOTSPOT_$1_CPU_DEFINE=S390
- elif test "x$OPENJDK_$1_CPU" = ss390x; then
+ elif test "x$OPENJDK_$1_CPU" = xs390x; then
HOTSPOT_$1_CPU_DEFINE=S390
fi
AC_SUBST(HOTSPOT_$1_CPU_DEFINE)
--- a/common/conf/jib-profiles.js Fri May 06 11:47:45 2016 +0300
+++ b/common/conf/jib-profiles.js Fri May 06 06:23:30 2016 -0700
@@ -212,14 +212,17 @@
* @returns Common values
*/
var getJibProfilesCommon = function (input) {
- var common = {
- dependencies: ["boot_jdk", "gnumake", "jtreg"],
- configure_args: ["--with-default-make-target=all", "--enable-jtreg-failure-handler"],
- configure_args_32bit: ["--with-target-bits=32", "--with-jvm-variants=client,server"],
- configure_args_debug: ["--enable-debug"],
- configure_args_slowdebug: ["--with-debug-level=slowdebug"],
- organization: "jpg.infra.builddeps"
- };
+ var common = {};
+
+ common.dependencies = ["boot_jdk", "gnumake", "jtreg"],
+ common.default_make_targets = ["product-images", "test-image"],
+ common.default_make_targets_debug = common.default_make_targets;
+ common.default_make_targets_slowdebug = common.default_make_targets;
+ common.configure_args = ["--enable-jtreg-failure-handler"],
+ common.configure_args_32bit = ["--with-target-bits=32", "--with-jvm-variants=client,server"],
+ common.configure_args_debug = ["--enable-debug"],
+ common.configure_args_slowdebug = ["--with-debug-level=slowdebug"],
+ common.organization = "jpg.infra.builddeps"
return common;
};
@@ -241,8 +244,8 @@
target_os: "linux",
target_cpu: "x64",
dependencies: concat(common.dependencies, "devkit"),
- configure_args: concat(common.configure_args, "--with-zlib=system"),
- make_args: common.make_args
+ configure_args: concat(common.configure_args, "--with-zlib=system"),
+ default_make_targets: concat(common.default_make_targets, "docs-image")
},
"linux-x86": {
@@ -252,39 +255,39 @@
dependencies: concat(common.dependencies, "devkit"),
configure_args: concat(common.configure_args, common.configure_args_32bit,
"--with-zlib=system"),
- make_args: common.make_args
+ default_make_targets: common.default_make_targets
},
"macosx-x64": {
target_os: "macosx",
target_cpu: "x64",
dependencies: concat(common.dependencies, "devkit"),
- configure_args: concat(common.configure_args, "--with-zlib=system"),
- make_args: common.make_args
+ configure_args: concat(common.configure_args, "--with-zlib=system"),
+ default_make_targets: common.default_make_targets
},
"solaris-x64": {
target_os: "solaris",
target_cpu: "x64",
dependencies: concat(common.dependencies, "devkit", "cups"),
- configure_args: concat(common.configure_args, "--with-zlib=system"),
- make_args: common.make_args
+ configure_args: concat(common.configure_args, "--with-zlib=system"),
+ default_make_targets: common.default_make_targets
},
"solaris-sparcv9": {
target_os: "solaris",
target_cpu: "sparcv9",
dependencies: concat(common.dependencies, "devkit", "cups"),
- configure_args: concat(common.configure_args, "--with-zlib=system"),
- make_args: common.make_args
+ configure_args: concat(common.configure_args, "--with-zlib=system"),
+ default_make_targets: common.default_make_targets
},
"windows-x64": {
target_os: "windows",
target_cpu: "x64",
dependencies: concat(common.dependencies, "devkit", "freetype"),
- configure_args: common.configure_args,
- make_args: common.make_args
+ configure_args: concat(common.configure_args),
+ default_make_targets: common.default_make_targets
},
"windows-x86": {
@@ -293,7 +296,7 @@
build_cpu: "x64",
dependencies: concat(common.dependencies, "devkit", "freetype"),
configure_args: concat(common.configure_args, common.configure_args_32bit),
- make_args: common.make_args
+ default_make_targets: common.default_make_targets
}
};
profiles = concatObjects(profiles, mainProfiles);
@@ -306,14 +309,15 @@
// implementation builds.
var openOnlyProfiles = generateOpenOnlyProfiles(common, mainProfiles);
// The open only profiles on linux are used for reference builds and should
- // produce the compact profile images by default.
+ // produce the compact profile images by default. This adds "profiles" as an
+ // extra default target.
var openOnlyProfilesExtra = {
"linux-x64-open": {
- configure_args: ["--with-default-make-target=all profiles"],
+ default_make_targets: "profiles"
},
"linux-x86-open": {
- configure_args: ["--with-default-make-target=all profiles"],
+ default_make_targets: "profiles"
}
};
var openOnlyProfiles = concatObjects(openOnlyProfiles, openOnlyProfilesExtra);
@@ -336,6 +340,7 @@
// Generate the missing platform attributes
profiles = generatePlatformAttributes(profiles);
+ profiles = generateDefaultMakeTargetsConfigureArg(common, profiles);
return profiles;
};
@@ -469,6 +474,8 @@
var debugProfile = profile + "-debug";
newProfiles[debugProfile] = clone(profiles[profile]);
newProfiles[debugProfile].debug_level = "fastdebug";
+ newProfiles[debugProfile].default_make_targets
+ = common.default_make_targets_debug;
newProfiles[debugProfile].labels
= concat(newProfiles[debugProfile].labels || [], "debug"),
newProfiles[debugProfile].configure_args
@@ -492,6 +499,8 @@
var debugProfile = profile + "-slowdebug";
newProfiles[debugProfile] = clone(profiles[profile]);
newProfiles[debugProfile].debug_level = "slowdebug";
+ newProfiles[debugProfile].default_make_targets
+ = common.default_make_targets_slowdebug;
newProfiles[debugProfile].labels
= concat(newProfiles[debugProfile].labels || [], "slowdebug"),
newProfiles[debugProfile].configure_args
@@ -524,6 +533,39 @@
};
/**
+ * The default_make_targets attribute on a profile is not a real Jib attribute.
+ * This function rewrites that attribute into the corresponding configure arg.
+ * Calling this function multiple times on the same profiles object is safe.
+ *
+ * @param common Common values
+ * @param profiles Profiles map to rewrite profiles for
+ * @returns {{}} New map of profiles with the make targets converted
+ */
+var generateDefaultMakeTargetsConfigureArg = function (common, profiles) {
+ var ret = concatObjects(profiles, {});
+ for (var profile in ret) {
+ if (ret[profile]["default_make_targets"] != null) {
+ var targetsString = concat(ret[profile].default_make_targets).join(" ");
+ // Iterate over all configure args and see if --with-default-make-target
+ // is already there and change it, otherwise add it.
+ var found = false;
+ for (var arg in ret[profile].configure_args) {
+ if (arg.startsWith("--with-default-make-target")) {
+ found = true;
+ arg.replace(/=.*/, "=" + targetsString);
+ }
+ }
+ if (!found) {
+ ret[profile].configure_args = concat(
+ ret[profile].configure_args,
+ "--with-default-make-target=" + targetsString);
+ }
+ }
+ }
+ return ret;
+}
+
+/**
* Deep clones an object tree.
*
* @param o Object to clone
--- a/corba/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/corba/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -358,3 +358,4 @@
cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113
10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114
7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115
+7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116
--- a/hotspot/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/hotspot/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -518,3 +518,4 @@
c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113
b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114
88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115
+61a214186dae6811dd989e9165e42f7dbf02acde jdk-9+116
--- a/jaxp/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/jaxp/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -358,3 +358,4 @@
28626780e245fccbfb9bad8e3b05f62357958038 jdk-9+113
147114dd0641cd7c9fe6e81642eb993a7b9c6f0b jdk-9+114
1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115
+9d71d20e614777cd23c1a43b38b5c08a9094d27a jdk-9+116
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java Fri May 06 11:47:45 2016 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java Fri May 06 06:23:30 2016 -0700
@@ -444,13 +444,15 @@
}
} else if (index == Feature.FILES.ordinal()) {
try {
- if (Util.verifyAndGetURI(value, null) == null) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
+ String[] catalogFile = value.split(";[ ]*");
+ for (String temp : catalogFile) {
+ if (Util.verifyAndGetURI(temp, null) == null) {
+ CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
+ }
}
}catch (MalformedURLException | URISyntaxException | IllegalArgumentException ex) {
CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, ex);
}
-
}
if (states[index] == null || state.compareTo(states[index]) >= 0) {
values[index] = value;
--- a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java Fri May 06 11:47:45 2016 +0300
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java Fri May 06 06:23:30 2016 -0700
@@ -91,6 +91,7 @@
permissions.add(new PropertyPermission("line.separator", "read"));
permissions.add(new PropertyPermission("fileStringBuffer", "read"));
permissions.add(new PropertyPermission("dataproviderthreadcount", "read"));
+ permissions.add(new RuntimePermission("charsetProvider"));
}
/*
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java Fri May 06 06:23:30 2016 -0700
@@ -23,6 +23,7 @@
package catalog;
import java.io.IOException;
+import java.nio.file.Paths;
import javax.xml.catalog.Catalog;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogFeatures;
@@ -34,6 +35,7 @@
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.xml.sax.Attributes;
@@ -44,10 +46,49 @@
import org.xml.sax.ext.DefaultHandler2;
/*
- * @bug 8081248, 8144966, 8146606, 8146237, 8151154, 8150969, 8151162, 8152527
+ * @bug 8081248, 8144966, 8146606, 8146237, 8151154, 8150969, 8151162, 8152527, 8154220
* @summary Tests basic Catalog functions.
*/
public class CatalogTest {
+ static final String KEY_FILES = "javax.xml.catalog.files";
+
+ public String filepath;
+
+ /*
+ * Initializing fields
+ */
+ @BeforeClass
+ public void setUpClass() throws Exception {
+ String file1 = getClass().getResource("first_cat.xml").getFile();
+ if (System.getProperty("os.name").contains("Windows")) {
+ filepath = file1.substring(1, file1.lastIndexOf("/") + 1);
+ } else {
+ filepath = file1.substring(0, file1.lastIndexOf("/") + 1);
+ }
+ }
+
+ /*
+ * @bug 8154220
+ * Verifies that the file input is validated properly. Valid input includes
+ * multiple file paths separated by semicolon.
+ */
+ @Test(dataProvider = "hierarchyOfCatFilesData")
+ public void hierarchyOfCatFiles2(String systemId, String expectedUri) {
+ String file1 = getClass().getResource("first_cat.xml").getFile();
+ String file2 = getClass().getResource("second_cat.xml").getFile();
+ String files = file1 + ";" + file2;
+
+ try {
+ System.setProperty(KEY_FILES, files);
+ CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults());
+ String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId();
+ Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), "System ID match not right");
+ } finally {
+ System.clearProperty(KEY_FILES);
+ }
+
+ }
+
/*
* @bug 8152527
* This test is the same as the JDK test ResolveEntityTests:testMatch1.
@@ -289,6 +330,19 @@
}
/*
+ DataProvider: used to verify hierarchical catalogs. Refer to JCK test
+ hierarchyOfCatFiles2.
+ */
+ @DataProvider(name = "hierarchyOfCatFilesData")
+ Object[][] getHierarchyOfCatFilesData() {
+ return new Object[][]{
+ {"http://www.oracle.com/sequence.dtd", "first.dtd"},
+ {"http://www.oracle.com/sequence_next.dtd", "next.dtd"},
+ {"http://www.oracle.com/sequence_second.dtd", "second.dtd"}
+ };
+ }
+
+ /*
DataProvider: used to verify CatalogResolver's resolveEntity function.
Data columns:
catalog, prefer, systemId, publicId, expectedUri, expectedFile, msg
@@ -300,6 +354,7 @@
{"rewriteSystem_id.xml", "system", "http://www.sys00test.com/rewrite.dtd", "PUB-404", expected, expected, "Relative rewriteSystem with xml:base at group level failed"},
};
}
+
static String id = "http://openjdk.java.net/xml/catalog/dtd/system.dtd";
/*
DataProvider: used to verify how prefer settings affect the result of the
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/first_cat.xml Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,6 @@
+<catalog prefer="system" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+ <system systemId="http://www.oracle.com/sequence.dtd" uri="first.dtd"/>
+ <nextCatalog catalog="next_cat.xml"/>
+
+</catalog>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/next_cat.xml Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,6 @@
+<catalog prefer="public" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+ <system systemId="http://www.oracle.com/sequence.dtd" uri="next.dtd"/>
+ <system systemId="http://www.oracle.com/sequence_next.dtd" uri="next.dtd"/>
+
+</catalog>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/second_cat.xml Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,7 @@
+<catalog prefer="public" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+ <system systemId="http://www.oracle.com/sequence.dtd" uri="second.dtd"/>
+ <system systemId="http://www.oracle.com/sequence_next.dtd" uri="second.dtd"/>
+ <system systemId="http://www.oracle.com/sequence_second.dtd" uri="second.dtd"/>
+
+</catalog>
\ No newline at end of file
--- a/jaxws/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/jaxws/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -361,3 +361,4 @@
e980062475c10d21137051045bf95ee229db9b27 jdk-9+113
b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114
4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115
+529f0bf896e58525614d863e283ad155531941cb jdk-9+116
--- a/jdk/make/Tools.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/Tools.gmk Fri May 06 06:23:30 2016 -0700
@@ -96,7 +96,13 @@
TOOL_SPP = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.tools.spp.Spp
# Nimbus is used somewhere in the swing build.
+
+ifeq ($(BOOT_JDK_MODULAR), true)
+ COMPILENIMBUS_ADD_MODS := -addmods java.xml.bind
+endif
+
TOOL_GENERATENIMBUS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
+ $(COMPILENIMBUS_ADD_MODS) \
build.tools.generatenimbus.Generator
TOOL_WRAPPERGENERATOR = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
--- a/jdk/make/gendata/Gendata-java.base.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/gendata/Gendata-java.base.gmk Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, 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
@@ -41,7 +41,7 @@
GENDATA_UNINAME := $(JDK_OUTPUTDIR)/modules/java.base/java/lang/uniName.dat
$(GENDATA_UNINAME): $(JDK_TOPDIR)/make/data/unicodedata/UnicodeData.txt $(BUILD_TOOLS_JDK)
- $(MKDIR) -p $(@D)
+ $(call MakeDir, $(@D))
$(TOOL_CHARACTERNAME) $< $@
TARGETS += $(GENDATA_UNINAME)
@@ -51,7 +51,7 @@
GENDATA_CURDATA := $(JDK_OUTPUTDIR)/modules/java.base/java/util/currency.data
$(GENDATA_CURDATA): $(JDK_TOPDIR)/make/data/currency/CurrencyData.properties $(BUILD_TOOLS_JDK)
- $(MKDIR) -p $(@D)
+ $(call MakeDir, $(@D))
$(RM) $@
$(TOOL_GENERATECURRENCYDATA) -o $@.tmp < $<
$(MV) $@.tmp $@
@@ -67,10 +67,10 @@
# RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile
$(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC)
- $(ECHO) "Generating java.security"
- $(MKDIR) -p $(@D)
+ $(call LogInfo, Generating java.security)
+ $(call MakeDir, $(@D))
$(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \
- $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC) || exit 1
+ $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC)
TARGETS += $(GENDATA_JAVA_SECURITY)
@@ -78,7 +78,7 @@
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/classlist: \
$(JDK_TOPDIR)/make/data/classlist/classlist.$(OPENJDK_TARGET_OS)
- $(MKDIR) -p $(@D)
+ $(call MakeDir, $(@D))
$(RM) $@ $@.tmp
$(TOOL_ADDJSUM) $< $@.tmp
$(MV) $@.tmp $@
--- a/jdk/make/gendata/GendataBreakIterator.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/gendata/GendataBreakIterator.gmk Fri May 06 06:23:30 2016 -0700
@@ -62,10 +62,13 @@
BIN := $(BREAK_ITERATOR_CLASSES)/jdk.localedata))
ifeq ($(BOOT_JDK_MODULAR), true)
- BREAK_ITERATOR_BOOTCLASSPATH := -Xpatch:$(BREAK_ITERATOR_CLASSES) \
- -XaddExports:java.base/sun.text=ALL-UNNAMED \
- -XaddExports:java.base/sun.text.resources=ALL-UNNAMED \
- -XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED
+ BREAK_ITERATOR_BOOTCLASSPATH := \
+ -Xpatch:java.base=$(BREAK_ITERATOR_CLASSES)/java.base \
+ -Xpatch:jdk.localedata=$(BREAK_ITERATOR_CLASSES)/jdk.localedata \
+ -XaddExports:java.base/sun.text=ALL-UNNAMED \
+ -XaddExports:java.base/sun.text.resources=ALL-UNNAMED \
+ -XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED \
+ #
else
BREAK_ITERATOR_BOOTCLASSPATH := -Xbootclasspath/p:$(call PathList, \
$(BREAK_ITERATOR_CLASSES)/java.base \
--- a/jdk/make/launcher/Launcher-java.desktop.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/launcher/Launcher-java.desktop.gmk Fri May 06 06:23:30 2016 -0700
@@ -31,7 +31,7 @@
ifndef BUILD_HEADLESS_ONLY
$(eval $(call SetupBuildLauncher, appletviewer, \
MAIN_CLASS := sun.applet.Main, \
- JAVA_ARGS := -addmods ALL-SYSTEM, \
+ JAVA_ARGS := -addmods ALL-DEFAULT, \
LIBS_unix := $(X_LIBS), \
))
endif
--- a/jdk/make/launcher/Launcher-java.scripting.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/launcher/Launcher-java.scripting.gmk Fri May 06 06:23:30 2016 -0700
@@ -27,4 +27,5 @@
$(eval $(call SetupBuildLauncher, jrunscript, \
MAIN_CLASS := com.sun.tools.script.shell.Main, \
+ JAVA_ARGS := -addmods ALL-DEFAULT, \
))
--- a/jdk/make/launcher/Launcher-jdk.compiler.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/launcher/Launcher-jdk.compiler.gmk Fri May 06 06:23:30 2016 -0700
@@ -27,7 +27,8 @@
$(eval $(call SetupBuildLauncher, javac, \
MAIN_CLASS := com.sun.tools.javac.Main, \
- CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ JAVA_ARGS := -addmods ALL-DEFAULT, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
))
--- a/jdk/make/launcher/Launcher-jdk.javadoc.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/launcher/Launcher-jdk.javadoc.gmk Fri May 06 06:23:30 2016 -0700
@@ -27,6 +27,7 @@
$(eval $(call SetupBuildLauncher, javadoc, \
MAIN_CLASS := jdk.javadoc.internal.tool.Main, \
+ JAVA_ARGS := -addmods ALL-DEFAULT, \
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
))
--- a/jdk/make/launcher/Launcher-jdk.jlink.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/launcher/Launcher-jdk.jlink.gmk Fri May 06 06:23:30 2016 -0700
@@ -32,6 +32,7 @@
$(eval $(call SetupBuildLauncher, jlink,\
MAIN_CLASS := jdk.tools.jlink.internal.Main, \
+ JAVA_ARGS := -addmods ALL-DEFAULT, \
CFLAGS := -DENABLE_ARG_FILES \
-DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
--- a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk Fri May 06 06:23:30 2016 -0700
@@ -27,6 +27,6 @@
$(eval $(call SetupBuildLauncher, jjs, \
MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \
- JAVA_ARGS := -addmods ALL-SYSTEM, \
+ JAVA_ARGS := -addmods ALL-DEFAULT, \
CFLAGS := -DENABLE_ARG_FILES, \
))
--- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers Fri May 06 06:23:30 2016 -0700
@@ -179,6 +179,7 @@
Java_sun_awt_UNIXToolkit_load_1gtk_1icon;
Java_sun_awt_UNIXToolkit_nativeSync;
Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl;
+ Java_sun_awt_UNIXToolkit_get_1gtk_1version;
Java_java_awt_AWTEvent_initIDs;
Java_java_awt_event_InputEvent_initIDs;
Java_java_awt_event_KeyEvent_initIDs;
--- a/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java Fri May 06 06:23:30 2016 -0700
@@ -54,13 +54,13 @@
return String.format(" d.put(\"%s%s\", \"%s\");\n",
prefix, getName(), getValue());
case INT:
- return String.format(" d.put(\"%s%s\", new Integer(%s));\n",
+ return String.format(" d.put(\"%s%s\", Integer.valueOf(%s));\n",
prefix, getName(), getValue());
case FLOAT:
- return String.format(" d.put(\"%s%s\", new Float(%sf));\n",
+ return String.format(" d.put(\"%s%s\", Float.valueOf(%sf));\n",
prefix, getName(), getValue());
case DOUBLE:
- return String.format(" d.put(\"%s%s\", new Double(%s));\n",
+ return String.format(" d.put(\"%s%s\", Double.valueOf(%s));\n",
prefix, getName(), getValue());
case COLOR:
return String.format(" addColor(d, \"%s%s\", %s);\n",
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Fri May 06 06:23:30 2016 -0700
@@ -102,7 +102,7 @@
@Override
FileTypeDetector getFileTypeDetector() {
- String userHome = GetPropertyAction.getProperty("user.home");
+ String userHome = GetPropertyAction.privilegedGetProperty("user.home");
Path userMimeTypes = Paths.get(userHome, ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
--- a/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, 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
@@ -53,7 +53,7 @@
start = t.tv_sec * 1000 + t.tv_usec / 1000;
for (;;) {
- int res = epoll_wait(epfd, events, numfds, timeout);
+ int res = epoll_wait(epfd, events, numfds, remaining);
if (res < 0 && errno == EINTR) {
if (remaining >= 0) {
gettimeofday(&t, NULL);
--- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Fri May 06 06:23:30 2016 -0700
@@ -84,7 +84,8 @@
static {
IOUtil.load();
initStructSizes();
- String datamodel = GetPropertyAction.getProperty("sun.arch.data.model");
+ String datamodel =
+ GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
is64bit = "64".equals(datamodel);
}
--- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java Fri May 06 06:23:30 2016 -0700
@@ -29,8 +29,6 @@
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
-import java.security.AccessController;
-import sun.security.action.GetPropertyAction;
import static sun.nio.fs.MacOSXNativeDispatcher.*;
--- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Fri May 06 06:23:30 2016 -0700
@@ -46,8 +46,8 @@
@Override
FileTypeDetector getFileTypeDetector() {
- Path userMimeTypes = Paths.get(
- GetPropertyAction.getProperty("user.home"), ".mime.types");
+ Path userMimeTypes = Paths.get(GetPropertyAction
+ .privilegedGetProperty("user.home"), ".mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
new UTIFileTypeDetector());
--- a/jdk/src/java.base/share/classes/java/io/File.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/io/File.java Fri May 06 06:23:30 2016 -0700
@@ -1896,7 +1896,7 @@
// temporary directory location
private static final File tmpdir = new File(
- GetPropertyAction.getProperty("java.io.tmpdir"));
+ GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
static File location() {
return tmpdir;
}
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Fri May 06 06:23:30 2016 -0700
@@ -470,7 +470,7 @@
* expression with an empty argument list. The class is initialized if it
* has not already been initialized.
*
- * <p>Note that this method propagates any exception thrown by the
+ * @deprecated This method propagates any exception thrown by the
* nullary constructor, including a checked exception. Use of
* this method effectively bypasses the compile-time exception
* checking that would otherwise be performed by the compiler.
@@ -500,6 +500,7 @@
* of this class.
*/
@CallerSensitive
+ @Deprecated(since="9")
public T newInstance()
throws InstantiationException, IllegalAccessException
{
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Fri May 06 06:23:30 2016 -0700
@@ -2615,7 +2615,7 @@
ServicesCatalog createOrGetServicesCatalog() {
ServicesCatalog catalog = servicesCatalog;
if (catalog == null) {
- catalog = new ServicesCatalog();
+ catalog = ServicesCatalog.create();
boolean set = trySetObjectField("servicesCatalog", catalog);
if (!set) {
// beaten by someone else
--- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -468,7 +468,7 @@
*/
public abstract static class Redirect {
private static final File NULL_FILE = new File(
- (GetPropertyAction.getProperty("os.name")
+ (GetPropertyAction.privilegedGetProperty("os.name")
.startsWith("Windows") ? "NUL" : "/dev/null")
);
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Fri May 06 06:23:30 2016 -0700
@@ -78,7 +78,8 @@
* Performance work and extensive testing is needed to replace the
* VM built-in backtrace filled in Throwable with the StackWalker.
*/
- final static boolean isDebug = getProperty("stackwalk.debug", false);
+ final static boolean isDebug =
+ "true".equals(GetPropertyAction.privilegedGetProperty("stackwalk.debug"));
static <T> StackFrameTraverser<T>
makeStackTraverser(StackWalker walker, Function<? super Stream<StackFrame>, ? extends T> function)
@@ -988,11 +989,4 @@
c.getName().startsWith("java.lang.invoke.LambdaForm");
}
- private static boolean getProperty(String key, boolean value) {
- String s = GetPropertyAction.getProperty(key);
- if (s != null) {
- return Boolean.parseBoolean(s);
- }
- return value;
- }
}
--- a/jdk/src/java.base/share/classes/java/lang/String.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/String.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -78,14 +78,8 @@
* <p>
* The Java language provides special support for the string
* concatenation operator ( + ), and for conversion of
- * other objects to strings. String concatenation is implemented
- * through the {@code StringBuilder}(or {@code StringBuffer})
- * class and its {@code append} method.
- * String conversions are implemented through the method
- * {@code toString}, defined by {@code Object} and
- * inherited by all classes in Java. For additional information on
- * string concatenation and conversion, see Gosling, Joy, and Steele,
- * <i>The Java Language Specification</i>.
+ * other objects to strings. For additional information on string
+ * concatenation and conversion, see <i>The Java™ Language Specification</i>.
*
* <p> Unless otherwise noted, passing a {@code null} argument to a constructor
* or method in this class will cause a {@link NullPointerException} to be
@@ -106,6 +100,14 @@
* into account. The {@link java.text.Collator} class provides methods for
* finer-grain, locale-sensitive String comparison.
*
+ * @implNote The implementation of the string concatenation operator is left to
+ * the discretion of a Java compiler, as long as the compiler ultimately conforms
+ * to <i>The Java™ Language Specification</i>. For example, the {@code javac} compiler
+ * may implement the operator with {@code StringBuffer}, {@code StringBuilder},
+ * or {@code java.lang.invoke.StringConcatFactory} depending on the JDK version. The
+ * implementation of string conversion is typically through the method {@code toString},
+ * defined by {@code Object} and inherited by all classes in Java.
+ *
* @author Lee Boynton
* @author Arthur van Hoff
* @author Martin Buchholz
@@ -115,6 +117,7 @@
* @see java.lang.StringBuilder
* @see java.nio.charset.Charset
* @since 1.0
+ * @jls 15.18.1 String Concatenation Operator +
*/
public final class String
@@ -2977,6 +2980,7 @@
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
+ * @jls 3.10.5 String Literals
*/
public native String intern();
--- a/jdk/src/java.base/share/classes/java/lang/System.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Fri May 06 06:23:30 2016 -0700
@@ -69,7 +69,6 @@
import jdk.internal.logger.LocalizedLoggerWrapper;
import jdk.internal.module.ModuleBootstrap;
-import jdk.internal.module.Modules;
import jdk.internal.module.ServicesCatalog;
/**
@@ -1924,10 +1923,6 @@
// initialize the module system
System.bootLayer = ModuleBootstrap.boot();
- // base module needs to be loose (CODETOOLS-7901619)
- Module base = Object.class.getModule();
- Modules.addReads(base, null);
-
// module system initialized
VM.initLevel(2);
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Fri May 06 06:23:30 2016 -0700
@@ -88,7 +88,7 @@
static {
final String key = "jdk.internal.lambda.dumpProxyClasses";
- String path = GetPropertyAction.getProperty(key);
+ String path = GetPropertyAction.privilegedGetProperty(key);
dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Fri May 06 06:23:30 2016 -0700
@@ -53,7 +53,7 @@
static final boolean VAR_HANDLE_GUARDS;
static {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean(
props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES"));
DUMP_CLASS_FILES = Boolean.parseBoolean(
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Fri May 06 06:23:30 2016 -0700
@@ -123,7 +123,7 @@
* Concatenation strategy to use. See {@link Strategy} for possible options.
* This option is controllable with -Djava.lang.invoke.stringConcat JDK option.
*/
- private static final Strategy STRATEGY;
+ private static Strategy STRATEGY;
/**
* Default strategy to use for concatenation.
@@ -187,7 +187,17 @@
private static final ProxyClassesDumper DUMPER;
static {
- Properties props = GetPropertyAction.getProperties();
+ // In case we need to double-back onto the StringConcatFactory during this
+ // static initialization, make sure we have the reasonable defaults to complete
+ // the static initialization properly. After that, actual users would use the
+ // the proper values we have read from the the properties.
+ STRATEGY = DEFAULT_STRATEGY;
+ // CACHE_ENABLE = false; // implied
+ // CACHE = null; // implied
+ // DEBUG = false; // implied
+ // DUMPER = null; // implied
+
+ Properties props = GetPropertyAction.privilegedGetProperties();
final String strategy =
props.getProperty("java.lang.invoke.stringConcat");
CACHE_ENABLE = Boolean.parseBoolean(
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java Fri May 06 06:23:30 2016 -0700
@@ -136,6 +136,7 @@
* consists of the methods
* {@link #compareAndSet compareAndSet},
* {@link #weakCompareAndSet weakCompareAndSet},
+ * {@link #weakCompareAndSetVolatile weakCompareAndSetVolatile},
* {@link #weakCompareAndSetAcquire weakCompareAndSetAcquire},
* {@link #weakCompareAndSetRelease weakCompareAndSetRelease},
* {@link #compareAndExchangeAcquire compareAndExchangeAcquire},
@@ -458,7 +459,7 @@
*
* <p>The symbolic type descriptor at the call site of {@code get}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.get)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.GET)} on this VarHandle.
*
* <p>This access mode is supported by all VarHandle instances and never
* throws {@code UnsupportedOperationException}.
@@ -488,7 +489,7 @@
*
* <p>The symbolic type descriptor at the call site of {@code set}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.set)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.SET)} on this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T newValue)}
@@ -516,7 +517,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code getVolatile}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.getVolatile)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.GET_VOLATILE)} on this
+ * VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT)}
@@ -544,7 +546,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code setVolatile}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.setVolatile)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.SET_VOLATILE)} on this
+ * VarHandle.
*
* @apiNote
* Ignoring the many semantic differences from C and C++, this method has
@@ -574,7 +577,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code getOpaque}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.getOpaque)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.GET_OPAQUE)} on this
+ * VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT)}
@@ -603,7 +607,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code setOpaque}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.setOpaque)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.SET_OPAQUE)} on this
+ * VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T newValue)}
@@ -631,7 +636,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code getAcquire}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.getAcquire)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.GET_ACQUIRE)} on this
+ * VarHandle.
*
* @apiNote
* Ignoring the many semantic differences from C and C++, this method has
@@ -664,7 +670,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code setRelease}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.setRelease)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.SET_RELEASE)} on this
+ * VarHandle.
*
* @apiNote
* Ignoring the many semantic differences from C and C++, this method has
@@ -700,7 +707,7 @@
*
* <p>The symbolic type descriptor at the call site of {@code
* compareAndSet} must match the access mode type that is the result of
- * calling {@code accessModeType(VarHandle.AccessMode.compareAndSet)} on
+ * calling {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_SET)} on
* this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
@@ -734,7 +741,7 @@
* <p>The symbolic type descriptor at the call site of {@code
* compareAndExchangeVolatile}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeVolatile)}
+ * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)}
* on this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
@@ -769,7 +776,7 @@
* <p>The symbolic type descriptor at the call site of {@code
* compareAndExchangeAcquire}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeAcquire)} on
+ * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)} on
* this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
@@ -804,7 +811,8 @@
* <p>The symbolic type descriptor at the call site of {@code
* compareAndExchangeRelease}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeRelease)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)}
+ * on this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T expectedValue, T newValue)}
@@ -836,14 +844,14 @@
* {@link #get}.
*
* <p>This operation may fail spuriously (typically, due to memory
- * contention) even if the current value does match the expected value.
+ * contention) even if the witness value does match the expected value.
*
* <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
*
* <p>The symbolic type descriptor at the call site of {@code
* weakCompareAndSet} must match the access mode type that is the result of
- * calling {@code accessModeType(VarHandle.AccessMode.weakCompareAndSet)} on
- * this VarHandle.
+ * calling {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)}
+ * on this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T expectedValue, T newValue)}
@@ -867,20 +875,58 @@
/**
* Possibly atomically sets the value of a variable to the {@code newValue}
+ * with the memory semantics of {@link #setVolatile} if the variable's
+ * current value, referred to as the <em>witness value</em>, {@code ==} the
+ * {@code expectedValue}, as accessed with the memory semantics of
+ * {@link #getVolatile}.
+ *
+ * <p>This operation may fail spuriously (typically, due to memory
+ * contention) even if the witness value does match the expected value.
+ *
+ * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+ *
+ * <p>The symbolic type descriptor at the call site of {@code
+ * weakCompareAndSetVolatile} must match the access mode type that is the
+ * result of calling {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)}
+ * on this VarHandle.
+ *
+ * @param args the signature-polymorphic parameter list of the form
+ * {@code (CT, T expectedValue, T newValue)}
+ * , statically represented using varargs.
+ * @return {@code true} if successful, otherwise {@code false} if the
+ * witness value was not the same as the {@code expectedValue} or if this
+ * operation spuriously failed.
+ * @throws UnsupportedOperationException if the access mode is unsupported
+ * for this VarHandle.
+ * @throws WrongMethodTypeException if the access mode type is not
+ * compatible with the caller's symbolic type descriptor.
+ * @throws ClassCastException if the access mode type is compatible with the
+ * caller's symbolic type descriptor, but a reference cast fails.
+ * @see #setVolatile(Object...)
+ * @see #getVolatile(Object...)
+ */
+ public final native
+ @MethodHandle.PolymorphicSignature
+ @HotSpotIntrinsicCandidate
+ boolean weakCompareAndSetVolatile(Object... args);
+
+ /**
+ * Possibly atomically sets the value of a variable to the {@code newValue}
* with the semantics of {@link #set} if the variable's current value,
* referred to as the <em>witness value</em>, {@code ==} the
* {@code expectedValue}, as accessed with the memory semantics of
* {@link #getAcquire}.
*
* <p>This operation may fail spuriously (typically, due to memory
- * contention) even if the current value does match the expected value.
+ * contention) even if the witness value does match the expected value.
*
* <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
*
* <p>The symbolic type descriptor at the call site of {@code
* weakCompareAndSetAcquire}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetAcquire)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)}
+ * on this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T expectedValue, T newValue)}
@@ -910,14 +956,15 @@
* {@link #get}.
*
* <p>This operation may fail spuriously (typically, due to memory
- * contention) even if the current value does match the expected value.
+ * contention) even if the witness value does match the expected value.
*
* <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
*
* <p>The symbolic type descriptor at the call site of {@code
* weakCompareAndSetRelease}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetRelease)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)}
+ * on this VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T expectedValue, T newValue)}
@@ -949,7 +996,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code getAndSet}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.getAndSet)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.GET_AND_SET)} on this
+ * VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T newValue)}
@@ -985,7 +1033,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code getAndAdd}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.getAndAdd)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.GET_AND_ADD)} on this
+ * VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T value)}
@@ -1017,7 +1066,8 @@
*
* <p>The symbolic type descriptor at the call site of {@code addAndGet}
* must match the access mode type that is the result of calling
- * {@code accessModeType(VarHandle.AccessMode.addAndGet)} on this VarHandle.
+ * {@code accessModeType(VarHandle.AccessMode.ADD_AND_GET)} on this
+ * VarHandle.
*
* @param args the signature-polymorphic parameter list of the form
* {@code (CT, T value)}
@@ -1083,109 +1133,115 @@
* method
* {@link VarHandle#get VarHandle.get}
*/
- GET("get", AccessType.GET, Object.class), // 0
+ GET("get", AccessType.GET, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#set VarHandle.set}
*/
- SET("set", AccessType.SET, void.class), // 1
+ SET("set", AccessType.SET, void.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#getVolatile VarHandle.getVolatile}
*/
- GET_VOLATILE("getVolatile", AccessType.GET, Object.class), // 2
+ GET_VOLATILE("getVolatile", AccessType.GET, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#setVolatile VarHandle.setVolatile}
*/
- SET_VOLATILE("setVolatile", AccessType.SET, void.class), // 3
+ SET_VOLATILE("setVolatile", AccessType.SET, void.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#getAcquire VarHandle.getAcquire}
*/
- GET_ACQUIRE("getAcquire", AccessType.GET, Object.class), // 4
+ GET_ACQUIRE("getAcquire", AccessType.GET, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#setRelease VarHandle.setRelease}
*/
- SET_RELEASE("setRelease", AccessType.SET, void.class), // 5
+ SET_RELEASE("setRelease", AccessType.SET, void.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#getOpaque VarHandle.getOpaque}
*/
- GET_OPAQUE("getOpaque", AccessType.GET, Object.class), // 6
+ GET_OPAQUE("getOpaque", AccessType.GET, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#setOpaque VarHandle.setOpaque}
*/
- SET_OPAQUE("setOpaque", AccessType.SET, void.class), // 7
+ SET_OPAQUE("setOpaque", AccessType.SET, void.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#compareAndSet VarHandle.compareAndSet}
*/
- COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), // 8
+ COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
*/
- COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 9
+ COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire}
*/
- COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 10
+ COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease}
*/
- COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 11
+ COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
*/
- WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), // 12
+ WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
+ /**
+ * The access mode whose access is specified by the corresponding
+ * method
+ * {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile}
+ */
+ WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP, boolean.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
*/
- WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class), // 13
+ WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
*/
- WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class), // 14
+ WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#getAndSet VarHandle.getAndSet}
*/
- GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class), // 15
+ GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#getAndAdd VarHandle.getAndAdd}
*/
- GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class), // 16
+ GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class),
/**
* The access mode whose access is specified by the corresponding
* method
* {@link VarHandle#addAndGet VarHandle.addAndGet}
*/
- ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class), // 17
+ ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class),
;
static final Map<String, AccessMode> methodNameToAccessMode;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Fri May 06 06:23:30 2016 -0700
@@ -155,6 +155,15 @@
}
@ForceInline
+ static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+ // TODO defer to strong form until new Unsafe method is added
+ return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+ handle.fieldOffset,
+ {#if[Object]?handle.fieldType.cast(expected):expected},
+ {#if[Object]?handle.fieldType.cast(value):value});
+ }
+
+ @ForceInline
static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
@@ -319,6 +328,15 @@
}
@ForceInline
+ static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+ // TODO defer to strong form until new Unsafe method is added
+ return UNSAFE.compareAndSwap$Type$(handle.base,
+ handle.fieldOffset,
+ {#if[Object]?handle.fieldType.cast(expected):expected},
+ {#if[Object]?handle.fieldType.cast(value):value});
+ }
+
+ @ForceInline
static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
handle.fieldOffset,
@@ -535,6 +553,20 @@
}
@ForceInline
+ static boolean weakCompareAndSetVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+ Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+ $type$[] array = ($type$[]) oarray;
+#end[Object]
+ // TODO defer to strong form until new Unsafe method is added
+ return UNSAFE.compareAndSwap$Type$(array,
+ (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+ {#if[Object]?handle.componentType.cast(expected):expected},
+ {#if[Object]?handle.componentType.cast(value):value});
+ }
+
+ @ForceInline
static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Fri May 06 06:23:30 2016 -0700
@@ -228,6 +228,16 @@
}
@ForceInline
+ static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+ byte[] ba = (byte[]) oba;
+ // TODO defer to strong form until new Unsafe method is added
+ return UNSAFE.compareAndSwap$RawType$(
+ ba,
+ address(ba, index(ba, index)),
+ convEndian(handle.be, expected), convEndian(handle.be, value));
+ }
+
+ @ForceInline
static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
@@ -444,6 +454,16 @@
}
@ForceInline
+ static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+ ByteBuffer bb = (ByteBuffer) obb;
+ // TODO defer to strong form until new Unsafe method is added
+ return UNSAFE.compareAndSwap$RawType$(
+ UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+ address(bb, indexRO(bb, index)),
+ convEndian(handle.be, expected), convEndian(handle.be, value));
+ }
+
+ @ForceInline
static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
--- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Fri May 06 06:23:30 2016 -0700
@@ -25,6 +25,7 @@
package java.lang.module;
+import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -183,17 +184,20 @@
this.nameToModule = Collections.emptyMap();
}
- private Configuration(Configuration parent, Resolver resolver) {
- Map<ResolvedModule, Set<ResolvedModule>> graph = resolver.finish(this);
+ private Configuration(Configuration parent,
+ Resolver resolver,
+ boolean check)
+ {
+ Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check);
Map<String, ResolvedModule> nameToModule = new HashMap<>();
- for (ResolvedModule resolvedModule : graph.keySet()) {
+ for (ResolvedModule resolvedModule : g.keySet()) {
nameToModule.put(resolvedModule.name(), resolvedModule);
}
this.parent = parent;
- this.graph = graph;
- this.modules = Collections.unmodifiableSet(graph.keySet());
+ this.graph = g;
+ this.modules = Collections.unmodifiableSet(g.keySet());
this.nameToModule = Collections.unmodifiableMap(nameToModule);
}
@@ -283,10 +287,10 @@
Objects.requireNonNull(after);
Objects.requireNonNull(roots);
- Resolver resolver = new Resolver(before, this, after);
+ Resolver resolver = new Resolver(before, this, after, null);
resolver.resolveRequires(roots);
- return new Configuration(this, resolver);
+ return new Configuration(this, resolver, true);
}
@@ -340,10 +344,32 @@
Objects.requireNonNull(after);
Objects.requireNonNull(roots);
- Resolver resolver = new Resolver(before, this, after);
+ Resolver resolver = new Resolver(before, this, after, null);
resolver.resolveRequires(roots).resolveUses();
- return new Configuration(this, resolver);
+ return new Configuration(this, resolver, true);
+ }
+
+
+ /**
+ * Resolves a collection of root modules, with service binding, and with
+ * the empty configuration as its parent. The post resolution checks
+ * are optionally run.
+ *
+ * This method is used to create the configuration for the boot layer.
+ */
+ static Configuration resolveRequiresAndUses(ModuleFinder finder,
+ Collection<String> roots,
+ boolean check,
+ PrintStream traceOutput)
+ {
+ Configuration parent = empty();
+
+ Resolver resolver
+ = new Resolver(finder, parent, ModuleFinder.empty(), traceOutput);
+ resolver.resolveRequires(roots).resolveUses();
+
+ return new Configuration(parent, resolver, check);
}
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Fri May 06 06:23:30 2016 -0700
@@ -27,13 +27,17 @@
import java.io.InputStream;
import java.io.IOException;
+import java.io.PrintStream;
import java.io.UncheckedIOException;
+import java.net.URI;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -45,7 +49,7 @@
import static java.util.Objects.*;
import jdk.internal.module.Checks;
-import jdk.internal.module.Hasher.DependencyHashes;
+import jdk.internal.module.ModuleHashes;
/**
@@ -372,8 +376,9 @@
private Provides(String service, Set<String> providers, boolean check) {
this.service = check ? requireServiceTypeName(service) : service;
- providers = check ? Collections.unmodifiableSet(new HashSet<>(providers))
- : Collections.unmodifiableSet(providers);
+ providers = check
+ ? Collections.unmodifiableSet(new LinkedHashSet<>(providers))
+ : Collections.unmodifiableSet(providers);
if (providers.isEmpty())
throw new IllegalArgumentException("Empty providers set");
if (check)
@@ -787,7 +792,7 @@
private final String osVersion;
private final Set<String> conceals;
private final Set<String> packages;
- private final DependencyHashes hashes;
+ private final ModuleHashes hashes;
private ModuleDescriptor(String name,
boolean automatic,
@@ -802,7 +807,7 @@
String osArch,
String osVersion,
Set<String> conceals,
- DependencyHashes hashes)
+ ModuleHashes hashes)
{
this.name = name;
@@ -878,7 +883,8 @@
String osArch,
String osVersion,
Set<String> conceals,
- Set<String> packages) {
+ Set<String> packages,
+ ModuleHashes hashes) {
this.name = name;
this.automatic = automatic;
this.synthetic = synthetic;
@@ -894,7 +900,7 @@
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
- this.hashes = null;
+ this.hashes = hashes;
}
/**
@@ -1063,9 +1069,9 @@
}
/**
- * Returns the object with the hashes of the dependences.
+ * Returns the object with the hashes of other modules
*/
- Optional<DependencyHashes> hashes() {
+ Optional<ModuleHashes> hashes() {
return Optional.ofNullable(hashes);
}
@@ -1103,7 +1109,7 @@
String osArch;
String osVersion;
String mainClass;
- DependencyHashes hashes;
+ ModuleHashes hashes;
/**
* Initializes a new builder with the given module name.
@@ -1580,7 +1586,7 @@
return this;
}
- /* package */ Builder hashes(DependencyHashes hashes) {
+ /* package */ Builder hashes(ModuleHashes hashes) {
this.hashes = hashes;
return this;
}
@@ -1719,7 +1725,9 @@
hc = hc * 43 + Objects.hashCode(osVersion);
hc = hc * 43 + Objects.hashCode(conceals);
hc = hc * 43 + Objects.hashCode(hashes);
- if (hc != 0) hash = hc;
+ if (hc == 0)
+ hc = -1;
+ hash = hc;
}
return hc;
}
@@ -1925,11 +1933,12 @@
static {
/**
- * Setup the shared secret to allow code in other packages create
- * ModuleDescriptor and associated objects directly.
+ * Setup the shared secret to allow code in other packages access
+ * private package methods in java.lang.module.
*/
jdk.internal.misc.SharedSecrets
.setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
+
@Override
public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
return new Requires(ms, mn, false);
@@ -1974,7 +1983,8 @@
String osArch,
String osVersion,
Set<String> conceals,
- Set<String> packages) {
+ Set<String> packages,
+ ModuleHashes hashes) {
return new ModuleDescriptor(name,
automatic,
synthetic,
@@ -1988,7 +1998,29 @@
osArch,
osVersion,
conceals,
- packages);
+ packages,
+ hashes);
+ }
+
+ @Override
+ public Configuration resolveRequiresAndUses(ModuleFinder finder,
+ Collection<String> roots,
+ boolean check,
+ PrintStream traceOutput)
+ {
+ return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
+ }
+
+ @Override
+ public ModuleReference newPatchedModule(ModuleDescriptor descriptor,
+ URI location,
+ Supplier<ModuleReader> s) {
+ return new ModuleReference(descriptor, location, s, true, null);
+ }
+
+ @Override
+ public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
+ return descriptor.hashes();
}
});
}
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java Fri May 06 06:23:30 2016 -0700
@@ -37,11 +37,12 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
-import jdk.internal.module.Hasher.DependencyHashes;
+import jdk.internal.module.ModuleHashes;
import static jdk.internal.module.ClassFileConstants.*;
@@ -337,7 +338,7 @@
// computeIfAbsent
Set<String> providers = pm.get(sn);
if (providers == null) {
- providers = new HashSet<>();
+ providers = new LinkedHashSet<>(); // preserve order
pm.put(sn, providers);
}
providers.add(cn);
@@ -425,7 +426,7 @@
map.put(dn, hash);
}
- builder.hashes(new DependencyHashes(algorithm, map));
+ builder.hashes(new ModuleHashes(algorithm, map));
}
--- a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java Fri May 06 06:23:30 2016 -0700
@@ -40,7 +40,7 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -52,7 +52,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -190,18 +189,16 @@
}
}
- if (attrs.isRegularFile() || attrs.isDirectory()) {
- // packaged or exploded module
- ModuleReference mref = readModule(entry, attrs);
- if (mref != null) {
- String name = mref.descriptor().name();
- return Collections.singletonMap(name, mref);
- }
+ // packaged or exploded module
+ ModuleReference mref = readModule(entry, attrs);
+ if (mref != null) {
+ String name = mref.descriptor().name();
+ return Collections.singletonMap(name, mref);
+ } else {
+ // skipped
+ return Collections.emptyMap();
}
- // not recognized
- throw new FindException("Unrecognized module: " + entry);
-
} catch (IOException ioe) {
throw new FindException(ioe);
}
@@ -238,16 +235,13 @@
// module found
if (mref != null) {
-
// can have at most one version of a module in the directory
String name = mref.descriptor().name();
if (nameToReference.put(name, mref) != null) {
throw new FindException("Two versions of module "
- + name + " found in " + dir);
+ + name + " found in " + dir);
}
-
}
-
}
}
@@ -257,28 +251,40 @@
/**
* Locates a packaged or exploded module, returning a {@code ModuleReference}
- * to the module. Returns {@code null} if the module is not recognized
- * as a packaged or exploded module.
+ * to the module. Returns {@code null} if the entry is skipped because it is
+ * to a directory that does not contain a module-info.class or it's a hidden
+ * file.
*
* @throws IOException if an I/O error occurs
- * @throws FindException if an error occurs parsing the module descriptor
+ * @throws FindException if the file is not recognized as a module or an
+ * error occurs parsing its module descriptor
*/
private ModuleReference readModule(Path entry, BasicFileAttributes attrs)
throws IOException
{
try {
- ModuleReference mref = null;
if (attrs.isDirectory()) {
- mref = readExplodedModule(entry);
- } if (attrs.isRegularFile()) {
- if (entry.toString().endsWith(".jar")) {
- mref = readJar(entry);
- } else if (isLinkPhase && entry.toString().endsWith(".jmod")) {
- mref = readJMod(entry);
+ return readExplodedModule(entry); // may return null
+ }
+
+ String fn = entry.getFileName().toString();
+ if (attrs.isRegularFile()) {
+ if (fn.endsWith(".jar")) {
+ return readJar(entry);
+ } else if (fn.endsWith(".jmod")) {
+ if (isLinkPhase)
+ return readJMod(entry);
+ throw new FindException("JMOD files not supported: " + entry);
}
}
- return mref;
+
+ // skip hidden files
+ if (fn.startsWith(".") || Files.isHidden(entry)) {
+ return null;
+ } else {
+ throw new FindException("Unrecognized module: " + entry);
+ }
} catch (InvalidModuleDescriptorException e) {
throw new FindException("Error reading module: " + entry, e);
@@ -292,15 +298,17 @@
return zf.stream()
.filter(e -> e.getName().startsWith("classes/") &&
e.getName().endsWith(".class"))
- .map(e -> toPackageName(e))
+ .map(e -> toPackageName(e.getName().substring(8)))
.filter(pkg -> pkg.length() > 0) // module-info
- .distinct()
.collect(Collectors.toSet());
}
/**
* Returns a {@code ModuleReference} to a module in jmod file on the
* file system.
+ *
+ * @throws IOException
+ * @throws InvalidModuleDescriptorException
*/
private ModuleReference readJMod(Path file) throws IOException {
try (ZipFile zf = new ZipFile(file.toString())) {
@@ -419,13 +427,12 @@
// scan the entries in the JAR file to locate the .class and service
// configuration file
- Stream<String> stream = jf.stream()
- .map(e -> e.getName())
- .filter(e -> (e.endsWith(".class") || e.startsWith(SERVICES_PREFIX)))
- .distinct();
- Map<Boolean, Set<String>> map
- = stream.collect(Collectors.partitioningBy(s -> s.endsWith(".class"),
- Collectors.toSet()));
+ Map<Boolean, Set<String>> map =
+ jf.stream()
+ .map(JarEntry::getName)
+ .filter(s -> (s.endsWith(".class") ^ s.startsWith(SERVICES_PREFIX)))
+ .collect(Collectors.partitioningBy(s -> s.endsWith(".class"),
+ Collectors.toSet()));
Set<String> classFiles = map.get(Boolean.TRUE);
Set<String> configFiles = map.get(Boolean.FALSE);
@@ -433,19 +440,18 @@
classFiles.stream()
.map(c -> toPackageName(c))
.distinct()
- .forEach(p -> builder.exports(p));
+ .forEach(builder::exports);
// map names of service configuration files to service names
Set<String> serviceNames = configFiles.stream()
.map(this::toServiceName)
- .filter(Optional::isPresent)
- .map(Optional::get)
+ .flatMap(Optional::stream)
.collect(Collectors.toSet());
// parse each service configuration file
for (String sn : serviceNames) {
JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
- Set<String> providerClasses = new HashSet<>();
+ Set<String> providerClasses = new LinkedHashSet<>();
try (InputStream in = jf.getInputStream(entry)) {
BufferedReader reader
= new BufferedReader(new InputStreamReader(in, "UTF-8"));
@@ -475,19 +481,25 @@
private Set<String> jarPackages(JarFile jf) {
return jf.stream()
.filter(e -> e.getName().endsWith(".class"))
- .map(e -> toPackageName(e))
+ .map(e -> toPackageName(e.getName()))
.filter(pkg -> pkg.length() > 0) // module-info
- .distinct()
.collect(Collectors.toSet());
}
/**
* Returns a {@code ModuleReference} to a module in modular JAR file on
* the file system.
+ *
+ * @throws IOException
+ * @throws FindException
+ * @throws InvalidModuleDescriptorException
*/
private ModuleReference readJar(Path file) throws IOException {
- try (JarFile jf = new JarFile(file.toString())) {
-
+ try (JarFile jf = new JarFile(file.toFile(),
+ true, // verify
+ ZipFile.OPEN_READ,
+ JarFile.Release.RUNTIME))
+ {
ModuleDescriptor md;
JarEntry entry = jf.getJarEntry(MODULE_INFO);
if (entry == null) {
@@ -520,7 +532,6 @@
path.toString().endsWith(".class")))
.map(path -> toPackageName(dir.relativize(path)))
.filter(pkg -> pkg.length() > 0) // module-info
- .distinct()
.collect(Collectors.toSet());
} catch (IOException x) {
throw new UncheckedIOException(x);
@@ -530,6 +541,9 @@
/**
* Returns a {@code ModuleReference} to an exploded module on the file
* system or {@code null} if {@code module-info.class} not found.
+ *
+ * @throws IOException
+ * @throws InvalidModuleDescriptorException
*/
private ModuleReference readExplodedModule(Path dir) throws IOException {
Path mi = dir.resolve(MODULE_INFO);
@@ -559,19 +573,6 @@
}
}
- private String toPackageName(ZipEntry entry) {
- String name = entry.getName();
- assert name.endsWith(".class");
- // jmod classes in classes/, jar in /
- int start = name.startsWith("classes/") ? 8 : 0;
- int index = name.lastIndexOf("/");
- if (index > start) {
- return name.substring(start, index).replace('/', '.');
- } else {
- return "";
- }
- }
-
private String toPackageName(Path path) {
String name = path.toString();
assert name.endsWith(".class");
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java Fri May 06 06:23:30 2016 -0700
@@ -142,10 +142,11 @@
* @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain)
*/
default Optional<ByteBuffer> read(String name) throws IOException {
- Optional<InputStream> in = open(name);
- if (in.isPresent()) {
- byte[] bytes = in.get().readAllBytes();
- return Optional.of(ByteBuffer.wrap(bytes));
+ Optional<InputStream> oin = open(name);
+ if (oin.isPresent()) {
+ try (InputStream in = oin.get()) {
+ return Optional.of(ByteBuffer.wrap(in.readAllBytes()));
+ }
} else {
return Optional.empty();
}
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
import java.util.Optional;
import java.util.function.Supplier;
-import jdk.internal.module.Hasher.HashSupplier;
+import jdk.internal.module.ModuleHashes.HashSupplier;
/**
@@ -54,12 +54,33 @@
private final URI location;
private final Supplier<ModuleReader> readerSupplier;
+ // true if this is a reference to a patched module
+ private boolean patched;
+
// the function that computes the hash of this module reference
private final HashSupplier hasher;
// cached hash string to avoid needing to compute it many times
private String cachedHash;
+
+ /**
+ * Constructs a new instance of this class.
+ */
+ ModuleReference(ModuleDescriptor descriptor,
+ URI location,
+ Supplier<ModuleReader> readerSupplier,
+ boolean patched,
+ HashSupplier hasher)
+
+ {
+ this.descriptor = Objects.requireNonNull(descriptor);
+ this.location = location;
+ this.readerSupplier = Objects.requireNonNull(readerSupplier);
+ this.patched = patched;
+ this.hasher = hasher;
+ }
+
/**
* Constructs a new instance of this class.
*/
@@ -67,11 +88,9 @@
URI location,
Supplier<ModuleReader> readerSupplier,
HashSupplier hasher)
+
{
- this.descriptor = Objects.requireNonNull(descriptor);
- this.location = location;
- this.readerSupplier = Objects.requireNonNull(readerSupplier);
- this.hasher = hasher;
+ this(descriptor, location, readerSupplier, false, hasher);
}
@@ -96,10 +115,9 @@
URI location,
Supplier<ModuleReader> readerSupplier)
{
- this(descriptor, location, readerSupplier, null);
+ this(descriptor, location, readerSupplier, false, null);
}
-
/**
* Returns the module descriptor.
*
@@ -151,6 +169,20 @@
/**
+ * Returns {@code true} if this module has been patched via -Xpatch.
+ */
+ boolean isPatched() {
+ return patched;
+ }
+
+ /**
+ * Returns the hash supplier for this module.
+ */
+ HashSupplier hasher() {
+ return hasher;
+ }
+
+ /**
* Computes the hash of this module, returning it as a hex string.
* Returns {@code null} if the hash cannot be computed.
*
@@ -166,8 +198,6 @@
return result;
}
- private int hash;
-
/**
* Computes a hash code for this module reference.
*
@@ -181,12 +211,17 @@
public int hashCode() {
int hc = hash;
if (hc == 0) {
- hc = Objects.hash(descriptor, location, readerSupplier, hasher);
- if (hc != 0) hash = hc;
+ hc = Objects.hash(descriptor, location, readerSupplier, hasher,
+ Boolean.valueOf(patched));
+ if (hc == 0)
+ hc = -1;
+ hash = hc;
}
return hc;
}
+ private int hash;
+
/**
* Tests this module reference for equality with the given object.
*
@@ -214,7 +249,8 @@
return Objects.equals(this.descriptor, that.descriptor)
&& Objects.equals(this.location, that.location)
&& Objects.equals(this.readerSupplier, that.readerSupplier)
- && Objects.equals(this.hasher, that.hasher);
+ && Objects.equals(this.hasher, that.hasher)
+ && this.patched == that.patched;
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java Fri May 06 06:23:30 2016 -0700
@@ -48,8 +48,8 @@
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
-import jdk.internal.module.Hasher;
-import jdk.internal.module.Hasher.HashSupplier;
+import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleHashes.HashSupplier;
import jdk.internal.module.ModulePatcher;
import sun.net.www.ParseUtil;
@@ -89,7 +89,7 @@
static ModuleReference newJarModule(ModuleDescriptor md, Path file) {
URI uri = file.toUri();
Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
- HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm);
+ HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a);
return newModule(md, uri, supplier, hasher);
}
@@ -99,7 +99,7 @@
static ModuleReference newJModModule(ModuleDescriptor md, Path file) {
URI uri = file.toUri();
Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
- HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm);
+ HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a);
return newModule(md, file.toUri(), supplier, hasher);
}
@@ -122,7 +122,7 @@
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
- private volatile boolean closed;
+ private boolean closed;
SafeCloseModuleReader() { }
@@ -198,7 +198,10 @@
static JarFile newJarFile(Path path) {
try {
- return new JarFile(path.toFile());
+ return new JarFile(path.toFile(),
+ true, // verify
+ ZipFile.OPEN_READ,
+ JarFile.Release.RUNTIME);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
@@ -219,6 +222,8 @@
if (je != null) {
String encodedPath = ParseUtil.encodePath(name, false);
String uris = "jar:" + uri + "!/" + encodedPath;
+ if (jf.isMultiRelease())
+ uris += "#runtime";
return Optional.of(URI.create(uris));
} else {
return Optional.empty();
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Fri May 06 06:23:30 2016 -0700
@@ -25,8 +25,8 @@
package java.lang.module;
+import java.io.PrintStream;
import java.lang.module.ModuleDescriptor.Requires.Modifier;
-import java.lang.reflect.Layer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
@@ -43,7 +43,7 @@
import java.util.StringJoiner;
import java.util.stream.Collectors;
-import jdk.internal.module.Hasher;
+import jdk.internal.module.ModuleHashes;
/**
* The resolver used by {@link Configuration#resolveRequires} and
@@ -55,6 +55,7 @@
private final ModuleFinder beforeFinder;
private final Configuration parent;
private final ModuleFinder afterFinder;
+ private final PrintStream traceOutput;
// maps module name to module reference
private final Map<String, ModuleReference> nameToReference = new HashMap<>();
@@ -62,10 +63,12 @@
Resolver(ModuleFinder beforeFinder,
Configuration parent,
- ModuleFinder afterFinder) {
+ ModuleFinder afterFinder,
+ PrintStream traceOutput) {
this.beforeFinder = beforeFinder;
this.parent = parent;
this.afterFinder = afterFinder;
+ this.traceOutput = traceOutput;
}
@@ -76,8 +79,6 @@
*/
Resolver resolveRequires(Collection<String> roots) {
- long start = trace_start("Resolve");
-
// create the visit stack to get us started
Deque<ModuleDescriptor> q = new ArrayDeque<>();
for (String root : roots) {
@@ -95,10 +96,9 @@
}
}
- if (TRACE) {
+ if (isTracing()) {
trace("Root module %s located", root);
- if (mref.location().isPresent())
- trace(" (%s)", mref.location().get());
+ mref.location().ifPresent(uri -> trace(" (%s)", uri));
}
assert mref.descriptor().name().equals(root);
@@ -108,13 +108,6 @@
resolve(q);
- if (TRACE) {
- long duration = System.currentTimeMillis() - start;
- Set<String> names = nameToReference.keySet();
- trace("Resolver completed in %s ms", duration);
- names.stream().sorted().forEach(name -> trace(" %s", name));
- }
-
return this;
}
@@ -153,11 +146,10 @@
q.offer(mref.descriptor());
resolved.add(mref.descriptor());
- if (TRACE) {
+ if (isTracing()) {
trace("Module %s located, required by %s",
dn, descriptor.name());
- if (mref.location().isPresent())
- trace(" (%s)", mref.location().get());
+ mref.location().ifPresent(uri -> trace(" (%s)", uri));
}
}
@@ -175,8 +167,6 @@
*/
Resolver resolveUses() {
- long start = trace_start("Bind");
-
// Scan the finders for all available service provider modules. As
// java.base uses services then then module finders will be scanned
// anyway.
@@ -230,10 +220,10 @@
String pn = provider.name();
if (!nameToReference.containsKey(pn)) {
-
- if (TRACE && mref.location().isPresent())
- trace(" (%s)", mref.location().get());
-
+ if (isTracing()) {
+ mref.location()
+ .ifPresent(uri -> trace(" (%s)", uri));
+ }
nameToReference.put(pn, mref);
q.push(provider);
}
@@ -248,14 +238,6 @@
} while (!candidateConsumers.isEmpty());
-
- if (TRACE) {
- long duration = System.currentTimeMillis() - start;
- Set<String> names = nameToReference.keySet();
- trace("Bind completed in %s ms", duration);
- names.stream().sorted().forEach(name -> trace(" %s", name));
- }
-
return this;
}
@@ -264,23 +246,33 @@
* Execute post-resolution checks and returns the module graph of resolved
* modules as {@code Map}. The resolved modules will be in the given
* configuration.
+ *
+ * @param check {@true} to execute the post resolution checks
*/
- Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf) {
+ Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf,
+ boolean check)
+ {
+ if (isTracing()) {
+ trace("Result:");
+ Set<String> names = nameToReference.keySet();
+ names.stream().sorted().forEach(name -> trace(" %s", name));
+ }
- detectCycles();
-
- checkPlatformConstraints();
-
- checkHashes();
+ if (check) {
+ detectCycles();
+ checkPlatformConstraints();
+ checkHashes();
+ }
Map<ResolvedModule, Set<ResolvedModule>> graph = makeGraph(cf);
- checkExportSuppliers(graph);
+ if (check) {
+ checkExportSuppliers(graph);
+ }
return graph;
}
-
/**
* Checks the given module graph for cycles.
*
@@ -420,52 +412,44 @@
}
-
/**
* Checks the hashes in the module descriptor to ensure that they match
- * the hash of the dependency's module reference.
+ * any recorded hashes.
*/
private void checkHashes() {
-
for (ModuleReference mref : nameToReference.values()) {
ModuleDescriptor descriptor = mref.descriptor();
- // get map of module names to hash
- Optional<Hasher.DependencyHashes> ohashes = descriptor.hashes();
+ // get map of module hashes
+ Optional<ModuleHashes> ohashes = descriptor.hashes();
if (!ohashes.isPresent())
continue;
- Hasher.DependencyHashes hashes = ohashes.get();
-
- // check dependences
- for (ModuleDescriptor.Requires d : descriptor.requires()) {
- String dn = d.name();
- String recordedHash = hashes.hashFor(dn);
-
- if (recordedHash != null) {
+ ModuleHashes hashes = ohashes.get();
- ModuleReference other = nameToReference.get(dn);
- if (other == null) {
- other = parent.findModule(dn)
- .map(ResolvedModule::reference)
- .orElse(null);
- }
- if (other == null)
- throw new InternalError(dn + " not found");
+ String algorithm = hashes.algorithm();
+ for (String dn : hashes.names()) {
+ ModuleReference other = nameToReference.get(dn);
+ if (other == null) {
+ other = parent.findModule(dn)
+ .map(ResolvedModule::reference)
+ .orElse(null);
+ }
- String actualHash = other.computeHash(hashes.algorithm());
+ // skip checking the hash if the module has been patched
+ if (other != null && !other.isPatched()) {
+ String recordedHash = hashes.hashFor(dn);
+ String actualHash = other.computeHash(algorithm);
if (actualHash == null)
fail("Unable to compute the hash of module %s", dn);
-
if (!recordedHash.equals(actualHash)) {
- fail("Hash of %s (%s) differs to expected hash (%s)",
- dn, actualHash, recordedHash);
+ fail("Hash of %s (%s) differs to expected hash (%s)" +
+ " recorded in %s", dn, actualHash, recordedHash,
+ descriptor.name());
}
+ }
+ }
- }
-
- }
}
-
}
@@ -666,7 +650,7 @@
// source is exported to descriptor2
String source = export.source();
ModuleDescriptor other
- = packageToExporter.put(source, descriptor2);
+ = packageToExporter.put(source, descriptor2);
if (other != null && other != descriptor2) {
// package might be local to descriptor1
@@ -690,33 +674,38 @@
}
}
- // uses S
- for (String service : descriptor1.uses()) {
- String pn = packageName(service);
- if (!packageToExporter.containsKey(pn)) {
- fail("Module %s does not read a module that exports %s",
- descriptor1.name(), pn);
- }
- }
+ // uses/provides checks not applicable to automatic modules
+ if (!descriptor1.isAutomatic()) {
- // provides S
- for (Map.Entry<String, ModuleDescriptor.Provides> entry :
- descriptor1.provides().entrySet()) {
- String service = entry.getKey();
- ModuleDescriptor.Provides provides = entry.getValue();
-
- String pn = packageName(service);
- if (!packageToExporter.containsKey(pn)) {
- fail("Module %s does not read a module that exports %s",
- descriptor1.name(), pn);
+ // uses S
+ for (String service : descriptor1.uses()) {
+ String pn = packageName(service);
+ if (!packageToExporter.containsKey(pn)) {
+ fail("Module %s does not read a module that exports %s",
+ descriptor1.name(), pn);
+ }
}
- for (String provider : provides.providers()) {
- if (!packages.contains(packageName(provider))) {
- fail("Provider %s not in module %s",
- provider, descriptor1.name());
+ // provides S
+ for (Map.Entry<String, ModuleDescriptor.Provides> entry :
+ descriptor1.provides().entrySet()) {
+ String service = entry.getKey();
+ ModuleDescriptor.Provides provides = entry.getValue();
+
+ String pn = packageName(service);
+ if (!packageToExporter.containsKey(pn)) {
+ fail("Module %s does not read a module that exports %s",
+ descriptor1.name(), pn);
+ }
+
+ for (String provider : provides.providers()) {
+ if (!packages.contains(packageName(provider))) {
+ fail("Provider %s not in module %s",
+ provider, descriptor1.name());
+ }
}
}
+
}
}
@@ -796,27 +785,18 @@
throw new ResolutionException(msg);
}
-
/**
- * Tracing support, limited to boot layer for now.
+ * Tracing support
*/
- private final static boolean TRACE
- = Boolean.getBoolean("jdk.launcher.traceResolver")
- && (Layer.boot() == null);
-
- private String op;
-
- private long trace_start(String op) {
- this.op = op;
- return System.currentTimeMillis();
+ private boolean isTracing() {
+ return traceOutput != null;
}
private void trace(String fmt, Object ... args) {
- if (TRACE) {
- System.out.print("[" + op + "] ");
- System.out.format(fmt, args);
- System.out.println();
+ if (traceOutput != null) {
+ traceOutput.format("[Resolver] " + fmt, args);
+ traceOutput.println();
}
}
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java Fri May 06 06:23:30 2016 -0700
@@ -44,6 +44,7 @@
import jdk.internal.jimage.ImageLocation;
import jdk.internal.jimage.ImageReader;
import jdk.internal.jimage.ImageReaderFactory;
+import jdk.internal.module.ModuleHashes;
import jdk.internal.module.SystemModules;
import jdk.internal.module.ModulePatcher;
import jdk.internal.perf.PerfCounter;
@@ -101,13 +102,16 @@
for (int i = 0; i < n; i++) {
String mn = moduleNames[i];
ModuleDescriptor md;
+ String hash;
if (fastLoad) {
md = descriptors[i];
+ hash = SystemModules.MODULES_TO_HASH[i];
} else {
// fallback to read module-info.class
// if fast loading of ModuleDescriptors is disabled
ImageLocation location = imageReader.findLocation(mn, "module-info.class");
md = ModuleDescriptor.read(imageReader.getResourceBuffer(location));
+ hash = null;
}
if (!md.name().equals(mn))
throw new InternalError();
@@ -123,7 +127,8 @@
}
};
- ModuleReference mref = new ModuleReference(md, uri, readerSupplier);
+ ModuleReference mref =
+ new ModuleReference(md, uri, readerSupplier, hashSupplier(hash));
// may need a reference to a patched module if -Xpatch specified
mref = ModulePatcher.interposeIfNeeded(mref);
@@ -142,6 +147,18 @@
initTime.addElapsedTimeFrom(t0);
}
+ private static ModuleHashes.HashSupplier hashSupplier(String hash) {
+ if (hash == null)
+ return null;
+
+ return new ModuleHashes.HashSupplier() {
+ @Override
+ public String generate(String algorithm) {
+ return hash;
+ }
+ };
+ }
+
SystemModuleFinder() { }
@Override
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Fri May 06 06:23:30 2016 -0700
@@ -27,6 +27,7 @@
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ResolvedModule;
import java.util.Collections;
import java.util.HashMap;
@@ -41,6 +42,8 @@
import jdk.internal.loader.Loader;
import jdk.internal.loader.LoaderPool;
import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ServicesCatalog;
+import jdk.internal.module.ServicesCatalog.ServiceProvider;
import sun.security.util.SecurityConstants;
@@ -549,4 +552,55 @@
public static Layer boot() {
return SharedSecrets.getJavaLangAccess().getBootLayer();
}
+
+
+ /**
+ * Returns the ServicesCatalog for this Layer, creating it if not
+ * already created.
+ */
+ ServicesCatalog getServicesCatalog() {
+ ServicesCatalog servicesCatalog = this.servicesCatalog;
+ if (servicesCatalog != null)
+ return servicesCatalog;
+
+ Map<String, Set<ServiceProvider>> map = new HashMap<>();
+ for (Module m : nameToModule.values()) {
+ ModuleDescriptor descriptor = m.getDescriptor();
+ for (Provides provides : descriptor.provides().values()) {
+ String service = provides.service();
+ Set<ServiceProvider> providers
+ = map.computeIfAbsent(service, k -> new HashSet<>());
+ for (String pn : provides.providers()) {
+ providers.add(new ServiceProvider(m, pn));
+ }
+ }
+ }
+
+ ServicesCatalog catalog = new ServicesCatalog() {
+ @Override
+ public void register(Module module) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public Set<ServiceProvider> findServices(String service) {
+ Set<ServiceProvider> providers = map.get(service);
+ if (providers == null) {
+ return Collections.emptySet();
+ } else {
+ return Collections.unmodifiableSet(providers);
+ }
+ }
+ };
+
+ synchronized (this) {
+ servicesCatalog = this.servicesCatalog;
+ if (servicesCatalog == null) {
+ this.servicesCatalog = servicesCatalog = catalog;
+ }
+ }
+
+ return servicesCatalog;
+ }
+
+ private volatile ServicesCatalog servicesCatalog;
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java Fri May 06 06:23:30 2016 -0700
@@ -43,11 +43,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -142,9 +138,6 @@
this.name = null;
this.loader = loader;
this.descriptor = null;
-
- // unnamed modules are loose
- this.loose = true;
}
@@ -245,17 +238,27 @@
}
- // -- readability --
+ // --
+
+ // the special Module to mean reads or exported to "all unnamed modules"
+ private static final Module ALL_UNNAMED_MODULE = new Module(null);
- // true if this module reads all unnamed modules (a.k.a. loose module)
- private volatile boolean loose;
+ // special Module to mean exported to "everyone"
+ private static final Module EVERYONE_MODULE = new Module(null);
+
+ // exported to all modules
+ private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
+
+
+ // -- readability --
// the modules that this module permanently reads
// (will be final when the modules are defined in reverse topology order)
private volatile Set<Module> reads;
- // created lazily, additional modules that this module reflectively reads
- private volatile WeakSet<Module> transientReads;
+ // additional module (2nd key) that some module (1st key) reflectively reads
+ private static final WeakPairMap<Module, Module, Boolean> transientReads
+ = new WeakPairMap<>();
/**
@@ -284,22 +287,19 @@
// check if this module reads other
if (other.isNamed()) {
-
Set<Module> reads = this.reads; // volatile read
if (reads != null && reads.contains(other))
return true;
-
- } else {
-
- // loose modules read all unnamed modules
- if (this.loose)
- return true;
-
}
// check if this module reads the other module reflectively
- WeakSet<Module> tr = this.transientReads; // volatile read
- if (tr != null && tr.contains(other))
+ if (transientReads.containsKeyPair(this, other))
+ return true;
+
+ // if other is an unnamed module then check if this module reads
+ // all unnamed modules
+ if (!other.isNamed()
+ && transientReads.containsKeyPair(this, ALL_UNNAMED_MODULE))
return true;
return false;
@@ -346,8 +346,7 @@
}
/**
- * Makes the given {@code Module} readable to this module without
- * notifying the VM.
+ * Updates this module to read another module without notifying the VM.
*
* @apiNote This method is for VM white-box testing.
*/
@@ -361,40 +360,28 @@
* If {@code syncVM} is {@code true} then the VM is notified.
*/
private void implAddReads(Module other, boolean syncVM) {
+ Objects.requireNonNull(other);
// nothing to do
if (other == this || !this.isNamed())
return;
- // if the other is null then change this module to be loose.
- if (other == null) {
- if (syncVM)
- addReads0(this, null);
- this.loose = true;
- return;
- }
-
// check if we already read this module
Set<Module> reads = this.reads;
if (reads != null && reads.contains(other))
return;
// update VM first, just in case it fails
- if (syncVM)
- addReads0(this, other);
+ if (syncVM) {
+ if (other == ALL_UNNAMED_MODULE) {
+ addReads0(this, null);
+ } else {
+ addReads0(this, other);
+ }
+ }
// add reflective read
- WeakSet<Module> tr = this.transientReads;
- if (tr == null) {
- synchronized (this) {
- tr = this.transientReads;
- if (tr == null) {
- tr = new WeakSet<>();
- this.transientReads = tr;
- }
- }
- }
- tr.add(other);
+ transientReads.putIfAbsent(this, other, Boolean.TRUE);
}
@@ -404,15 +391,10 @@
// (will be final when the modules are defined in reverse topology order)
private volatile Map<String, Set<Module>> exports;
- // created lazily, additional exports added at run-time
- private volatile Map<String, WeakSet<Module>> transientExports;
-
- // the special Module to mean exported to all modules
- private static final Module EVERYONE_MODULE = new Module(null);
- private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
-
- // the special Module to mean exported to all unnamed modules
- private static final Module ALL_UNNAMED_MODULE = new Module(null);
+ // additional exports added at run-time
+ // this module (1st key), other module (2nd key), exported packages (value)
+ private static final WeakPairMap<Module, Module, Map<String, Boolean>>
+ transientExports = new WeakPairMap<>();
/**
@@ -489,23 +471,9 @@
if (exports != null) {
Set<Module> targets = exports.get(pn);
- if (targets != null) {
-
- // exported to all modules
- if (targets.contains(EVERYONE_MODULE))
- return true;
-
- if (other != EVERYONE_MODULE) {
- // exported to other
- if (targets.contains(other))
- return true;
-
- // other is an unnamed module && exported to all unnamed
- if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
- return true;
- }
-
- }
+ if ((targets != null)
+ && (targets.contains(other) || targets.contains(EVERYONE_MODULE)))
+ return true;
}
return false;
}
@@ -515,29 +483,27 @@
* package package to the given module.
*/
private boolean isExportedReflectively(String pn, Module other) {
- Map<String, WeakSet<Module>> te = this.transientExports;
- if (te != null) {
- WeakSet<Module> targets = te.get(pn);
+ // exported to all modules
+ Map<String, ?> exports = transientExports.get(this, EVERYONE_MODULE);
+ if (exports != null && exports.containsKey(pn))
+ return true;
- if (targets != null) {
-
- // exported to all modules
- if (targets.contains(EVERYONE_MODULE))
- return true;
+ if (other != EVERYONE_MODULE) {
- if (other != EVERYONE_MODULE) {
+ // exported to other
+ exports = transientExports.get(this, other);
+ if (exports != null && exports.containsKey(pn))
+ return true;
- // exported to other
- if (targets.contains(other))
- return true;
-
- // other is an unnamed module && exported to all unnamed
- if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
- return true;
- }
+ // other is an unnamed module && exported to all unnamed
+ if (!other.isNamed()) {
+ exports = transientExports.get(this, ALL_UNNAMED_MODULE);
+ if (exports != null && exports.containsKey(pn))
+ return true;
}
}
+
return false;
}
@@ -638,34 +604,19 @@
}
}
- // create transientExports if needed
- Map<String, WeakSet<Module>> te = this.transientExports; // read
- if (te == null) {
- synchronized (this) {
- te = this.transientExports;
- if (te == null) {
- te = new ConcurrentHashMap<>();
- this.transientExports = te; // volatile write
- }
- }
- }
-
// add package name to transientExports if absent
- WeakSet<Module> s = te.get(pn);
- if (s == null) {
- s = new WeakSet<>();
- WeakSet<Module> prev = te.putIfAbsent(pn, s);
- if (prev != null)
- s = prev;
- }
- s.add(other);
+ transientExports
+ .computeIfAbsent(this, other,
+ (_this, _other) -> new ConcurrentHashMap<>())
+ .putIfAbsent(pn, Boolean.TRUE);
}
// -- services --
- // created lazily, additional service types that this module uses
- private volatile WeakSet<Class<?>> transientUses;
+ // additional service type (2nd key) that some module (1st key) uses
+ private static final WeakPairMap<Module, Class<?>, Boolean> transientUses
+ = new WeakPairMap<>();
/**
* If the caller's module is this module then update this module to add a
@@ -702,17 +653,7 @@
}
if (!canUse(st)) {
- WeakSet<Class<?>> uses = this.transientUses;
- if (uses == null) {
- synchronized (this) {
- uses = this.transientUses;
- if (uses == null) {
- uses = new WeakSet<>();
- this.transientUses = uses;
- }
- }
- }
- uses.add(st);
+ transientUses.putIfAbsent(this, st, Boolean.TRUE);
}
}
@@ -746,11 +687,7 @@
return true;
// uses added via addUses
- WeakSet<Class<?>> uses = this.transientUses;
- if (uses != null && uses.contains(st))
- return true;
-
- return false;
+ return transientUses.containsKeyPair(this, st);
}
@@ -885,7 +822,7 @@
// -- creating Module objects --
/**
- * Find the runtime Module corresponding to the given ReadDependence
+ * Find the runtime Module corresponding to the given ResolvedModule
* in the given parent Layer (or its parents).
*/
private static Module find(ResolvedModule resolvedModule, Layer layer) {
@@ -969,7 +906,7 @@
// automatic modules reads all unnamed modules
if (descriptor.isAutomatic()) {
- m.implAddReads(null, true);
+ m.implAddReads(ALL_UNNAMED_MODULE, true);
}
// exports
@@ -1097,7 +1034,7 @@
* the representation is the string {@code "module"}, followed by a space,
* and then the module name. For an unnamed module, the representation is
* the string {@code "unnamed module"}, followed by a space, and then an
- * implementation specific identifier for the unnamed module.
+ * implementation specific string that identifies the unnamed module.
*
* @return The string representation of this module
*/
@@ -1112,46 +1049,6 @@
}
- // -- supporting classes --
-
-
- /**
- * A "not-a-Set" set of weakly referenced objects that supports concurrent
- * access.
- */
- private static class WeakSet<E> {
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
- private final Lock readLock = lock.readLock();
- private final Lock writeLock = lock.writeLock();
-
- private final WeakHashMap<E, Boolean> map = new WeakHashMap<>();
-
- /**
- * Adds the specified element to the set.
- */
- void add(E e) {
- writeLock.lock();
- try {
- map.put(e, Boolean.TRUE);
- } finally {
- writeLock.unlock();
- }
- }
-
- /**
- * Returns {@code true} if this set contains the specified element.
- */
- boolean contains(E e) {
- readLock.lock();
- try {
- return map.containsKey(e);
- } finally {
- readLock.unlock();
- }
- }
- }
-
-
// -- native methods --
// JVM_DefineModule
@@ -1196,8 +1093,12 @@
m1.implAddReads(m2, true);
}
@Override
+ public void addReadsAllUnnamed(Module m) {
+ m.implAddReads(Module.ALL_UNNAMED_MODULE);
+ }
+ @Override
public void addExports(Module m, String pn, Module other) {
- m.implAddExports(pn, Objects.requireNonNull(other), true);
+ m.implAddExports(pn, other, true);
}
@Override
public void addExportsToAll(Module m, String pn) {
@@ -1211,6 +1112,10 @@
public void addPackage(Module m, String pn) {
m.implAddPackage(pn, true);
}
+ @Override
+ public ServicesCatalog getServicesCatalog(Layer layer) {
+ return layer.getServicesCatalog();
+ }
});
}
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Fri May 06 06:23:30 2016 -0700
@@ -582,7 +582,7 @@
}
private static final String DEBUG =
- GetPropertyAction.getProperty("jdk.proxy.debug", "");
+ GetPropertyAction.privilegedGetProperty("jdk.proxy.debug", "");
private static boolean isDebug() {
return !DEBUG.isEmpty();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/WeakPairMap.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,354 @@
+/*
+ * 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 java.lang.reflect;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiFunction;
+
+/**
+ * A WeakHashMap-like data structure that uses a pair of weakly-referenced keys
+ * with identity equality semantics to associate a strongly-referenced value.
+ * Unlike WeakHashMap, this data structure is thread-safe.
+ *
+ * @param <K1> the type of 1st key in key pair
+ * @param <K2> the type of 2nd key in key pair
+ * @param <V> the type of value
+ * @author Peter Levart
+ */
+final class WeakPairMap<K1, K2, V> {
+
+ private final ConcurrentHashMap<Pair<K1, K2>, V> map = new ConcurrentHashMap<>();
+ private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
+
+ /**
+ * Tests if the specified pair of keys are associated with a value
+ * in the WeakPairMap.
+ *
+ * @param k1 the 1st of the pair of keys
+ * @param k2 the 2nd of the pair of keys
+ * @return true if and only if the specified key pair is in this WeakPairMap,
+ * as determined by the identity comparison; false otherwise
+ * @throws NullPointerException if any of the specified keys is null
+ */
+ public boolean containsKeyPair(K1 k1, K2 k2) {
+ expungeStaleAssociations();
+ return map.containsKey(Pair.lookup(k1, k2));
+ }
+
+ /**
+ * Returns the value to which the specified pair of keys is mapped, or null
+ * if this WeakPairMap contains no mapping for the key pair.
+ * <p>More formally, if this WeakPairMap contains a mapping from a key pair
+ * {@code (_k1, _k2)} to a value {@code v} such that
+ * {@code k1 == _k1 && k2 == _k2}, then this method returns {@code v};
+ * otherwise it returns {@code null}.
+ * (There can be at most one such mapping.)
+ *
+ * @param k1 the 1st of the pair of keys for which the mapped value is to
+ * be returned
+ * @param k2 the 2nd of the pair of keys for which the mapped value is to
+ * be returned
+ * @return the value to which the specified key pair is mapped, or null if
+ * this map contains no mapping for the key pair
+ * @throws NullPointerException if any of the specified keys is null
+ */
+ public V get(K1 k1, K2 k2) {
+ expungeStaleAssociations();
+ return map.get(Pair.lookup(k1, k2));
+ }
+
+ /**
+ * Maps the specified key pair to the specified value in this WeakPairMap.
+ * Neither the keys nor the value can be null.
+ * <p>The value can be retrieved by calling the {@link #get} method
+ * with the the same keys (compared by identity).
+ *
+ * @param k1 the 1st of the pair of keys with which the specified value is to
+ * be associated
+ * @param k2 the 2nd of the pair of keys with which the specified value is to
+ * be associated
+ * @param v value to be associated with the specified key pair
+ * @return the previous value associated with key pair, or {@code null} if
+ * there was no mapping for key pair
+ * @throws NullPointerException if any of the specified keys or value is null
+ */
+ public V put(K1 k1, K2 k2, V v) {
+ expungeStaleAssociations();
+ return map.put(Pair.weak(k1, k2, queue), v);
+ }
+
+ /**
+ * If the specified key pair is not already associated with a value,
+ * associates it with the given value and returns {@code null}, else does
+ * nothing and returns the currently associated value.
+ *
+ * @param k1 the 1st of the pair of keys with which the specified value is to
+ * be associated
+ * @param k2 the 2nd of the pair of keys with which the specified value is to
+ * be associated
+ * @param v value to be associated with the specified key pair
+ * @return the previous value associated with key pair, or {@code null} if
+ * there was no mapping for key pair
+ * @throws NullPointerException if any of the specified keys or value is null
+ */
+ public V putIfAbsent(K1 k1, K2 k2, V v) {
+ expungeStaleAssociations();
+ return map.putIfAbsent(Pair.weak(k1, k2, queue), v);
+ }
+
+ /**
+ * If the specified key pair is not already associated with a value,
+ * attempts to compute its value using the given mapping function
+ * and enters it into this WeakPairMap unless {@code null}. The entire
+ * method invocation is performed atomically, so the function is
+ * applied at most once per key pair. Some attempted update operations
+ * on this WeakPairMap by other threads may be blocked while computation
+ * is in progress, so the computation should be short and simple,
+ * and must not attempt to update any other mappings of this WeakPairMap.
+ *
+ * @param k1 the 1st of the pair of keys with which the
+ * computed value is to be associated
+ * @param k2 the 2nd of the pair of keys with which the
+ * computed value is to be associated
+ * @param mappingFunction the function to compute a value
+ * @return the current (existing or computed) value associated with
+ * the specified key pair, or null if the computed value is null
+ * @throws NullPointerException if any of the specified keys or
+ * mappingFunction is null
+ * @throws IllegalStateException if the computation detectably
+ * attempts a recursive update to this map
+ * that would otherwise never complete
+ * @throws RuntimeException or Error if the mappingFunction does so, in
+ * which case the mapping is left unestablished
+ */
+ public V computeIfAbsent(K1 k1, K2 k2,
+ BiFunction<? super K1, ? super K2, ? extends V>
+ mappingFunction) {
+ expungeStaleAssociations();
+ try {
+ return map.computeIfAbsent(
+ Pair.weak(k1, k2, queue),
+ pair -> mappingFunction.apply(pair.first(), pair.second()));
+ } finally {
+ Reference.reachabilityFence(k1);
+ Reference.reachabilityFence(k2);
+ }
+ }
+
+ /**
+ * Returns a {@link Collection} view of the values contained in this
+ * WeakPairMap. The collection is backed by the WeakPairMap, so changes to
+ * the map are reflected in the collection, and vice-versa. The collection
+ * supports element removal, which removes the corresponding
+ * mapping from this map, via the {@code Iterator.remove},
+ * {@code Collection.remove}, {@code removeAll},
+ * {@code retainAll}, and {@code clear} operations. It does not
+ * support the {@code add} or {@code addAll} operations.
+ *
+ * @return the collection view
+ */
+ public Collection<V> values() {
+ expungeStaleAssociations();
+ return map.values();
+ }
+
+ /**
+ * Removes associations from this WeakPairMap for which at least one of the
+ * keys in key pair has been found weakly-reachable and corresponding
+ * WeakRefPeer(s) enqueued. Called as part of each public operation.
+ */
+ private void expungeStaleAssociations() {
+ WeakRefPeer<?> peer;
+ while ((peer = (WeakRefPeer<?>) queue.poll()) != null) {
+ map.remove(peer.weakPair());
+ }
+ }
+
+ /**
+ * Common interface of both {@link Weak} and {@link Lookup} key pairs.
+ */
+ private interface Pair<K1, K2> {
+
+ static <K1, K2> Pair<K1, K2> weak(K1 k1, K2 k2,
+ ReferenceQueue<Object> queue) {
+ return new Weak<>(k1, k2, queue);
+ }
+
+ static <K1, K2> Pair<K1, K2> lookup(K1 k1, K2 k2) {
+ return new Lookup<>(k1, k2);
+ }
+
+ /**
+ * @return The 1st of the pair of keys (may be null for {@link Weak}
+ * when it gets cleared)
+ */
+ K1 first();
+
+ /**
+ * @return The 2nd of the pair of keys (may be null for {@link Weak}
+ * when it gets cleared)
+ */
+ K2 second();
+
+ static int hashCode(Object first, Object second) {
+ // assert first != null && second != null;
+ return System.identityHashCode(first) ^
+ System.identityHashCode(second);
+ }
+
+ static boolean equals(Object first, Object second, Pair<?, ?> p) {
+ return first != null && second != null &&
+ first == p.first() && second == p.second();
+ }
+
+ /**
+ * A Pair where both keys are weakly-referenced.
+ * It is composed of two instances of {@link WeakRefPeer}s:
+ * <pre>{@code
+ *
+ * +-referent-> [K1] +-referent-> [K2]
+ * | |
+ * +----------------+ +----------------+
+ * | Pair.Weak <: |-----peer----->| (anonymous) <: |
+ * | WeakRefPeer, | | WeakRefPeer |
+ * | Pair |<--weakPair()--| |
+ * +----------------+ +----------------+
+ * | ^
+ * | |
+ * +-weakPair()-+
+ *
+ * }</pre>
+ * <p>
+ * Pair.Weak is used for CHM keys. Both peers are associated with the
+ * same {@link ReferenceQueue} so when either of their referents
+ * becomes weakly-reachable, the corresponding entries can be
+ * {@link #expungeStaleAssociations() expunged} from the map.
+ */
+ final class Weak<K1, K2> extends WeakRefPeer<K1> implements Pair<K1, K2> {
+
+ // saved hash so it can be retrieved after the reference is cleared
+ private final int hash;
+ // link to <K2> peer
+ private final WeakRefPeer<K2> peer;
+
+ Weak(K1 k1, K2 k2, ReferenceQueue<Object> queue) {
+ super(k1, queue);
+ hash = Pair.hashCode(k1, k2);
+ peer = new WeakRefPeer<>(k2, queue) {
+ // link back to <K1> peer
+ @Override
+ Weak<?, ?> weakPair() { return Weak.this; }
+ };
+ }
+
+ @Override
+ Weak<?, ?> weakPair() {
+ return this;
+ }
+
+ @Override
+ public K1 first() {
+ return get();
+ }
+
+ @Override
+ public K2 second() {
+ return peer.get();
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this == obj ||
+ (obj instanceof Pair &&
+ Pair.equals(first(), second(), (Pair<?, ?>) obj));
+ }
+ }
+
+ /**
+ * Optimized lookup Pair, used as lookup key in methods like
+ * {@link java.util.Map#get(Object)} or
+ * {@link java.util.Map#containsKey(Object)}) where
+ * there is a great chance its allocation is eliminated
+ * by escape analysis when such lookups are inlined by JIT.
+ * All its methods are purposely designed so that 'this' is never
+ * passed to any other method or used as identity.
+ */
+ final class Lookup<K1, K2> implements Pair<K1, K2> {
+ private final K1 k1;
+ private final K2 k2;
+
+ Lookup(K1 k1, K2 k2) {
+ this.k1 = Objects.requireNonNull(k1);
+ this.k2 = Objects.requireNonNull(k2);
+ }
+
+ @Override
+ public K1 first() {
+ return k1;
+ }
+
+ @Override
+ public K2 second() {
+ return k2;
+ }
+
+ @Override
+ public int hashCode() {
+ return Pair.hashCode(k1, k2);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Pair &&
+ Pair.equals(k1, k2, (Pair<?, ?>) obj);
+ }
+ }
+ }
+
+ /**
+ * Common abstract supertype of a pair of WeakReference peers.
+ */
+ private static abstract class WeakRefPeer<K> extends WeakReference<K> {
+
+ WeakRefPeer(K k, ReferenceQueue<Object> queue) {
+ super(Objects.requireNonNull(k), queue);
+ }
+
+ /**
+ * @return the {@link Pair.Weak} side of the pair of peers.
+ */
+ abstract Pair.Weak<?, ?> weakPair();
+ }
+}
--- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java Fri May 06 06:23:30 2016 -0700
@@ -1536,7 +1536,7 @@
* be performed to generate a result with the specified scale, the
* specified rounding mode is applied.
*
- * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method
+ * @deprecated The method {@link #divide(BigDecimal, int, RoundingMode)}
* should be used in preference to this legacy method.
*
* @param divisor value by which this {@code BigDecimal} is to be divided.
@@ -1558,6 +1558,7 @@
* @see #ROUND_HALF_EVEN
* @see #ROUND_UNNECESSARY
*/
+ @Deprecated(since="9")
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
throw new IllegalArgumentException("Invalid rounding mode");
@@ -1602,7 +1603,7 @@
* rounding must be performed to generate a result with the given
* scale, the specified rounding mode is applied.
*
- * <p>The new {@link #divide(BigDecimal, RoundingMode)} method
+ * @deprecated The method {@link #divide(BigDecimal, RoundingMode)}
* should be used in preference to this legacy method.
*
* @param divisor value by which this {@code BigDecimal} is to be divided.
@@ -1623,6 +1624,7 @@
* @see #ROUND_HALF_EVEN
* @see #ROUND_UNNECESSARY
*/
+ @Deprecated(since="9")
public BigDecimal divide(BigDecimal divisor, int roundingMode) {
return this.divide(divisor, scale, roundingMode);
}
@@ -2267,14 +2269,20 @@
* Rounding mode to round away from zero. Always increments the
* digit prior to a nonzero discarded fraction. Note that this rounding
* mode never decreases the magnitude of the calculated value.
+ *
+ * @deprecated Use {@link RoundingMode#UP} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_UP = 0;
/**
* Rounding mode to round towards zero. Never increments the digit
* prior to a discarded fraction (i.e., truncates). Note that this
* rounding mode never increases the magnitude of the calculated value.
+ *
+ * @deprecated Use {@link RoundingMode#DOWN} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_DOWN = 1;
/**
@@ -2283,7 +2291,10 @@
* {@code ROUND_UP}; if negative, behaves as for
* {@code ROUND_DOWN}. Note that this rounding mode never
* decreases the calculated value.
+ *
+ * @deprecated Use {@link RoundingMode#CEILING} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_CEILING = 2;
/**
@@ -2292,7 +2303,10 @@
* {@code ROUND_DOWN}; if negative, behave as for
* {@code ROUND_UP}. Note that this rounding mode never
* increases the calculated value.
+ *
+ * @deprecated Use {@link RoundingMode#FLOOR} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_FLOOR = 3;
/**
@@ -2302,7 +2316,10 @@
* ≥ 0.5; otherwise, behaves as for {@code ROUND_DOWN}. Note
* that this is the rounding mode that most of us were taught in
* grade school.
+ *
+ * @deprecated Use {@link RoundingMode#HALF_UP} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_HALF_UP = 4;
/**
@@ -2311,7 +2328,10 @@
* down. Behaves as for {@code ROUND_UP} if the discarded
* fraction is {@literal >} 0.5; otherwise, behaves as for
* {@code ROUND_DOWN}.
+ *
+ * @deprecated Use {@link RoundingMode#HALF_DOWN} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_HALF_DOWN = 5;
/**
@@ -2323,7 +2343,10 @@
* {@code ROUND_HALF_DOWN} if it's even. Note that this is the
* rounding mode that minimizes cumulative error when applied
* repeatedly over a sequence of calculations.
+ *
+ * @deprecated Use {@link RoundingMode#HALF_EVEN} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_HALF_EVEN = 6;
/**
@@ -2331,7 +2354,10 @@
* result, hence no rounding is necessary. If this rounding mode is
* specified on an operation that yields an inexact result, an
* {@code ArithmeticException} is thrown.
+ *
+ * @deprecated Use {@link RoundingMode#UNNECESSARY} instead.
*/
+ @Deprecated(since="9")
public static final int ROUND_UNNECESSARY = 7;
@@ -2408,7 +2434,7 @@
* Instead, {@code setScale} returns an object with the proper
* scale; the returned object may or may not be newly allocated.
*
- * <p>The new {@link #setScale(int, RoundingMode)} method should
+ * @deprecated The method {@link #setScale(int, RoundingMode)} should
* be used in preference to this legacy method.
*
* @param newScale scale of the {@code BigDecimal} value to be returned.
@@ -2431,6 +2457,7 @@
* @see #ROUND_HALF_EVEN
* @see #ROUND_UNNECESSARY
*/
+ @Deprecated(since="9")
public BigDecimal setScale(int newScale, int roundingMode) {
if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
throw new IllegalArgumentException("Invalid rounding mode");
--- a/jdk/src/java.base/share/classes/java/math/RoundingMode.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/math/RoundingMode.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, 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
@@ -90,6 +90,7 @@
* @author Joseph D. Darcy
* @since 1.5
*/
+@SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal
public enum RoundingMode {
/**
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Fri May 06 06:23:30 2016 -0700
@@ -52,7 +52,8 @@
protected InetAddress connectedAddress = null;
private int connectedPort = -1;
- private static final String os = GetPropertyAction.getProperty("os.name");
+ private static final String os =
+ GetPropertyAction.privilegedGetProperty("os.name");
/**
* flag set if the native connect() call not to be used
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java Fri May 06 06:23:30 2016 -0700
@@ -1124,7 +1124,7 @@
private static NameService createNameService() {
String hostsFileName =
- GetPropertyAction.getProperty("jdk.net.hosts.file");
+ GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
NameService theNameService;
if (hostsFileName != null) {
theNameService = new HostsFileNameService(hostsFileName);
@@ -1643,9 +1643,11 @@
* property can vary across implementations of the java.
* classes. The default is an empty String "".
*/
- String prefix = GetPropertyAction.getProperty("impl.prefix", "");
+ String prefix = GetPropertyAction.privilegedGetProperty("impl.prefix", "");
try {
- impl = Class.forName("java.net." + prefix + implName).newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName("java.net." + prefix + implName).newInstance();
+ impl = tmp;
} catch (ClassNotFoundException e) {
System.err.println("Class not found: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
@@ -1662,7 +1664,9 @@
if (impl == null) {
try {
- impl = Class.forName(implName).newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(implName).newInstance();
+ impl = tmp;
} catch (Exception e) {
throw new Error("System property impl.prefix incorrect");
}
--- a/jdk/src/java.base/share/classes/java/net/ProxySelector.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/ProxySelector.java Fri May 06 06:23:30 2016 -0700
@@ -71,7 +71,9 @@
try {
Class<?> c = Class.forName("sun.net.spi.DefaultProxySelector");
if (c != null && ProxySelector.class.isAssignableFrom(c)) {
- theProxySelector = (ProxySelector) c.newInstance();
+ @SuppressWarnings("deprecation")
+ ProxySelector tmp = (ProxySelector) c.newInstance();
+ theProxySelector = tmp;
}
} catch (Exception e) {
theProxySelector = null;
--- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Fri May 06 06:23:30 2016 -0700
@@ -178,7 +178,7 @@
userName = pw.getUserName();
password = new String(pw.getPassword());
} else {
- userName = GetPropertyAction.getProperty("user.name");
+ userName = GetPropertyAction.privilegedGetProperty("user.name");
}
if (userName == null)
return false;
@@ -1088,7 +1088,7 @@
userName = System.getProperty("user.name");
} catch (SecurityException se) { /* swallow Exception */ }
} else {
- userName = GetPropertyAction.getProperty("user.name");
+ userName = GetPropertyAction.privilegedGetProperty("user.name");
}
return userName;
}
--- a/jdk/src/java.base/share/classes/java/net/URL.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/URL.java Fri May 06 06:23:30 2016 -0700
@@ -1198,8 +1198,9 @@
public URLStreamHandler createURLStreamHandler(String protocol) {
String name = PREFIX + "." + protocol + ".Handler";
try {
- Class<?> c = Class.forName(name);
- return (URLStreamHandler)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName(name).newInstance();
+ return (URLStreamHandler)o;
} catch (ClassNotFoundException x) {
// ignore
} catch (Exception e) {
@@ -1212,7 +1213,7 @@
private static URLStreamHandler lookupViaProperty(String protocol) {
String packagePrefixList =
- GetPropertyAction.getProperty(protocolPathProp);
+ GetPropertyAction.privilegedGetProperty(protocolPathProp);
if (packagePrefixList == null) {
// not set
return null;
@@ -1234,7 +1235,9 @@
}
}
if (cls != null) {
- handler = (URLStreamHandler)cls.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = cls.newInstance();
+ handler = (URLStreamHandler)tmp;
}
} catch (Exception e) {
// any number of exceptions can get thrown here
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -1323,7 +1323,9 @@
}
}
if (cls != null) {
- return (ContentHandler) cls.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = cls.newInstance();
+ return (ContentHandler) tmp;
}
} catch(Exception ignored) { }
}
@@ -1397,7 +1399,7 @@
*/
private String getContentHandlerPkgPrefixes() {
String packagePrefixList =
- GetPropertyAction.getProperty(contentPathProp, "");
+ GetPropertyAction.privilegedGetProperty(contentPathProp, "");
if (packagePrefixList != "") {
packagePrefixList += "|";
--- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java Fri May 06 06:23:30 2016 -0700
@@ -133,7 +133,7 @@
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');
- dfltEncName = GetPropertyAction.getProperty("file.encoding");
+ dfltEncName = GetPropertyAction.privilegedGetProperty("file.encoding");
}
/**
--- a/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java Fri May 06 06:23:30 2016 -0700
@@ -94,9 +94,10 @@
if (cn == null)
return null;
try {
- Class<?> c = Class.forName(cn, true,
- ClassLoader.getSystemClassLoader());
- return (AsynchronousChannelProvider)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(cn, true,
+ ClassLoader.getSystemClassLoader()).newInstance();
+ return (AsynchronousChannelProvider)tmp;
} catch (ClassNotFoundException x) {
throw new ServiceConfigurationError(null, x);
} catch (IllegalAccessException x) {
--- a/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java Fri May 06 06:23:30 2016 -0700
@@ -95,9 +95,10 @@
if (cn == null)
return false;
try {
- Class<?> c = Class.forName(cn, true,
- ClassLoader.getSystemClassLoader());
- provider = (SelectorProvider)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(cn, true,
+ ClassLoader.getSystemClassLoader()).newInstance();
+ provider = (SelectorProvider)tmp;
return true;
} catch (ClassNotFoundException x) {
throw new ServiceConfigurationError(null, x);
--- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Fri May 06 06:23:30 2016 -0700
@@ -283,8 +283,8 @@
if (level == null) {
if (!VM.isBooted())
return false;
- bugLevel = level =
- GetPropertyAction.getProperty("sun.nio.cs.bugLevel", "");
+ bugLevel = level = GetPropertyAction
+ .privilegedGetProperty("sun.nio.cs.bugLevel", "");
}
return level.equals(bl);
}
@@ -609,7 +609,8 @@
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
- String csn = GetPropertyAction.getProperty("file.encoding");
+ String csn = GetPropertyAction
+ .privilegedGetProperty("file.encoding");
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
--- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Fri May 06 06:23:30 2016 -0700
@@ -46,7 +46,7 @@
// temporary directory location
private static final Path tmpdir =
- Paths.get(GetPropertyAction.getProperty("java.io.tmpdir"));
+ Paths.get(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
private static final boolean isPosix =
FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
--- a/jdk/src/java.base/share/classes/java/security/Policy.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/security/Policy.java Fri May 06 06:23:30 2016 -0700
@@ -222,8 +222,9 @@
public Policy run() {
try {
ClassLoader scl = ClassLoader.getSystemClassLoader();
- Class<?> c = Class.forName(policyProvider, true, scl);
- return (Policy)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName(policyProvider, true, scl).newInstance();
+ return (Policy)o;
} catch (Exception e) {
if (debug != null) {
debug.println("policy provider " + policyProvider +
--- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java Fri May 06 06:23:30 2016 -0700
@@ -147,6 +147,7 @@
if (prop != null) {
try {
Class<?> c = Class.forName(prop, true, ClassLoader.getSystemClassLoader());
+ @SuppressWarnings("deprecation")
ZoneRulesProvider provider = ZoneRulesProvider.class.cast(c.newInstance());
registerProvider(provider);
loaded.add(provider);
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -4403,6 +4403,35 @@
public void sort(Comparator<? super E> c) {
Arrays.sort(a, c);
}
+
+ @Override
+ public Iterator<E> iterator() {
+ return new ArrayItr<>(a);
+ }
+ }
+
+ private static class ArrayItr<E> implements Iterator<E> {
+ private int cursor;
+ private final E[] a;
+
+ ArrayItr(E[] a) {
+ this.a = a;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cursor < a.length;
+ }
+
+ @Override
+ public E next() {
+ int i = cursor;
+ if (i >= a.length) {
+ throw new NoSuchElementException();
+ }
+ cursor = i + 1;
+ return a[i];
+ }
}
/**
--- a/jdk/src/java.base/share/classes/java/util/Locale.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Locale.java Fri May 06 06:23:30 2016 -0700
@@ -858,7 +858,7 @@
private static Locale initDefault() {
String language, region, script, country, variant;
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
language = props.getProperty("user.language", "en");
// for compatibility, check for old user.region property
region = props.getProperty("user.region");
@@ -883,7 +883,7 @@
}
private static Locale initDefault(Locale.Category category) {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
return getInstance(
props.getProperty(category.languageKey,
defaultLocale.getLanguage()),
--- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Fri May 06 06:23:30 2016 -0700
@@ -140,9 +140,8 @@
// Check whether the strict encoding is specified.
// The possible encoding is either "ISO-8859-1" or "UTF-8".
- private static final String encoding =
- GetPropertyAction
- .getProperty("java.util.PropertyResourceBundle.encoding", "")
+ private static final String encoding = GetPropertyAction
+ .privilegedGetProperty("java.util.PropertyResourceBundle.encoding", "")
.toUpperCase(Locale.ROOT);
/**
--- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java Fri May 06 06:23:30 2016 -0700
@@ -29,8 +29,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Provides;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Layer;
@@ -85,7 +83,7 @@
* and deployed as a named module must have an appropriate <i>uses</i> clause
* in its <i>module descriptor</i> to declare that the module uses
* implementations of the service. A corresponding requirement is that a
- * provider deployed as a named modules must have an appropriate
+ * provider deployed as a named module must have an appropriate
* <i>provides</i> clause in its module descriptor to declare that the module
* provides an implementation of the service. The <i>uses</i> and
* <i>provides</i> allow consumers of a service to be <i>linked</i> to
@@ -550,35 +548,29 @@
/**
* Implements lazy service provider lookup of service providers that
* are provided by modules in a module Layer.
- *
- * For now, this iterator examines all modules in each Layer. This will
- * be replaced once we decide on how the service-use graph is exposed
- * in the module API.
*/
private class LayerLookupIterator
extends RestrictedIterator<S>
{
final String serviceName;
Layer currentLayer;
- Iterator<ModuleDescriptor> descriptorIterator;
- Iterator<String> providersIterator;
-
- Module nextModule;
- String nextProvider;
+ Iterator<ServiceProvider> iterator;
+ ServiceProvider nextProvider;
LayerLookupIterator() {
serviceName = service.getName();
currentLayer = layer;
// need to get us started
- descriptorIterator = descriptors(layer, serviceName);
+ iterator = providers(currentLayer, serviceName);
}
- Iterator<ModuleDescriptor> descriptors(Layer layer, String service) {
- return layer.modules().stream()
- .map(Module::getDescriptor)
- .filter(d -> d.provides().get(service) != null)
- .iterator();
+ Iterator<ServiceProvider> providers(Layer layer, String service) {
+ ServicesCatalog catalog = SharedSecrets
+ .getJavaLangReflectModuleAccess()
+ .getServicesCatalog(layer);
+
+ return catalog.findServices(serviceName).iterator();
}
@Override
@@ -591,30 +583,18 @@
while (true) {
// next provider
- if (providersIterator != null && providersIterator.hasNext()) {
- nextProvider = providersIterator.next();
+ if (iterator != null && iterator.hasNext()) {
+ nextProvider = iterator.next();
return true;
}
- // next descriptor
- if (descriptorIterator.hasNext()) {
- ModuleDescriptor descriptor = descriptorIterator.next();
-
- nextModule = currentLayer.findModule(descriptor.name()).get();
-
- Provides provides = descriptor.provides().get(serviceName);
- providersIterator = provides.providers().iterator();
-
- continue;
- }
-
// next layer
Layer parent = currentLayer.parent().orElse(null);
if (parent == null)
return false;
currentLayer = parent;
- descriptorIterator = descriptors(currentLayer, serviceName);
+ iterator = providers(currentLayer, serviceName);
}
}
@@ -623,13 +603,14 @@
if (!hasNextService())
throw new NoSuchElementException();
- assert nextModule != null && nextProvider != null;
-
- String cn = nextProvider;
+ ServiceProvider provider = nextProvider;
nextProvider = null;
+ Module module = provider.module();
+ String cn = provider.providerName();
+
// attempt to load the provider
- Class<?> c = loadClassInModule(nextModule, cn);
+ Class<?> c = loadClassInModule(module, cn);
if (c == null)
fail(service, "Provider " + cn + " not found");
if (!service.isAssignableFrom(c))
@@ -830,7 +811,9 @@
}
S p = null;
try {
- p = service.cast(c.newInstance());
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ p = service.cast(tmp);
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated",
--- a/jdk/src/java.base/share/classes/java/util/TimeZone.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/TimeZone.java Fri May 06 06:23:30 2016 -0700
@@ -42,6 +42,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.ZoneId;
+import java.util.Properties;
import sun.security.action.GetPropertyAction;
import sun.util.calendar.ZoneInfo;
import sun.util.calendar.ZoneInfoFile;
@@ -660,12 +661,13 @@
private static synchronized TimeZone setDefaultZone() {
TimeZone tz;
// get the time zone ID from the system properties
- String zoneID = GetPropertyAction.getProperty("user.timezone");
+ Properties props = GetPropertyAction.privilegedGetProperties();
+ String zoneID = props.getProperty("user.timezone");
// if the time zone ID is not set (yet), perform the
// platform to Java time zone ID mapping.
if (zoneID == null || zoneID.isEmpty()) {
- String javaHome = GetPropertyAction.getProperty("java.home");
+ String javaHome = props.getProperty("java.home");
try {
zoneID = getSystemTimeZoneID(javaHome);
if (zoneID == null) {
@@ -693,13 +695,7 @@
assert tz != null;
final String id = zoneID;
- AccessController.doPrivileged(new PrivilegedAction<>() {
- @Override
- public Void run() {
- System.setProperty("user.timezone", id);
- return null;
- }
- });
+ props.setProperty("user.timezone", id);
defaultTimeZone = tz;
return tz;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Fri May 06 06:23:30 2016 -0700
@@ -3507,6 +3507,7 @@
* Creates and returns the common pool, respecting user settings
* specified via system properties.
*/
+ @SuppressWarnings("deprecation") // Class.newInstance
static ForkJoinPool makeCommonPool() {
int parallelism = -1;
ForkJoinWorkerThreadFactory factory = null;
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Fri May 06 06:23:30 2016 -0700
@@ -155,7 +155,7 @@
BASE_VERSION = 8; // one less than lowest version for versioned entries
int runtimeVersion = jdk.Version.current().major();
String jarVersion =
- GetPropertyAction.getProperty("jdk.util.jar.version");
+ GetPropertyAction.privilegedGetProperty("jdk.util.jar.version");
if (jarVersion != null) {
int jarVer = Integer.parseInt(jarVersion);
runtimeVersion = (jarVer > runtimeVersion)
@@ -163,7 +163,7 @@
}
RUNTIME_VERSION = runtimeVersion;
String enableMultiRelease = GetPropertyAction
- .getProperty("jdk.util.jar.enableMultiRelease", "true");
+ .privilegedGetProperty("jdk.util.jar.enableMultiRelease", "true");
switch (enableMultiRelease) {
case "true":
default:
@@ -658,6 +658,28 @@
return vze == null ? ze : vze;
}
+ /**
+ * Returns the real name of a {@code JarEntry}. If this {@code JarFile} is
+ * a multi-release jar file and is configured to be processed as such, the
+ * name returned by this method is the path name of the versioned entry
+ * that the {@code JarEntry} represents, rather than the path name of the
+ * base entry that {@link JarEntry#getName()} returns. If the
+ * {@code JarEntry} does not represent a versioned entry, or the
+ * jar file is not a multi-release jar file or {@code JarFile} is not
+ * configured for processing a multi-release jar file, this method returns
+ * the same name that {@link JarEntry#getName()} returns.
+ *
+ * @param entry the JarEntry
+ * @return the real name of the JarEntry
+ * @since 9
+ */
+ String getRealName(JarEntry entry) {
+ if (entry instanceof JarFileEntry) {
+ return ((JarFileEntry)entry).realName();
+ }
+ return entry.getName();
+ }
+
private class JarFileEntry extends JarEntry {
final private String name;
@@ -684,7 +706,7 @@
throw new RuntimeException(e);
}
if (certs == null && jv != null) {
- certs = jv.getCerts(JarFile.this, reifiedEntry());
+ certs = jv.getCerts(JarFile.this, realEntry());
}
return certs == null ? null : certs.clone();
}
@@ -695,17 +717,20 @@
throw new RuntimeException(e);
}
if (signers == null && jv != null) {
- signers = jv.getCodeSigners(JarFile.this, reifiedEntry());
+ signers = jv.getCodeSigners(JarFile.this, realEntry());
}
return signers == null ? null : signers.clone();
}
- JarFileEntry reifiedEntry() {
+ JarFileEntry realEntry() {
if (isMultiRelease()) {
String entryName = super.getName();
return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this);
}
return this;
}
+ String realName() {
+ return super.getName();
+ }
@Override
public String getName() {
@@ -876,11 +901,11 @@
private JarEntry verifiableEntry(ZipEntry ze) {
if (ze instanceof JarFileEntry) {
// assure the name and entry match for verification
- return ((JarFileEntry)ze).reifiedEntry();
+ return ((JarFileEntry)ze).realEntry();
}
ze = getJarEntry(ze.getName());
if (ze instanceof JarFileEntry) {
- return ((JarFileEntry)ze).reifiedEntry();
+ return ((JarFileEntry)ze).realEntry();
}
return (JarEntry)ze;
}
--- a/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Fri May 06 06:23:30 2016 -0700
@@ -60,4 +60,8 @@
public List<Object> getManifestDigests(JarFile jar) {
return jar.getManifestDigests();
}
+
+ public String getRealName(JarFile jar, JarEntry entry) {
+ return jar.getRealName(entry);
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Fri May 06 06:23:30 2016 -0700
@@ -695,7 +695,7 @@
Class<?> impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl;
if (impl == null) {
// The first time, we must decide which class to use.
- implName = GetPropertyAction.getProperty(prop,"");
+ implName = GetPropertyAction.privilegedGetProperty(prop,"");
if (implName != null && !implName.equals(""))
impl = Class.forName(implName);
else if (PACK_PROVIDER.equals(prop))
@@ -704,7 +704,9 @@
impl = com.sun.java.util.jar.pack.UnpackerImpl.class;
}
// We have a class. Now instantiate it.
- return impl.newInstance();
+ @SuppressWarnings("deprecation")
+ Object result = impl.newInstance();
+ return result;
} catch (ClassNotFoundException e) {
throw new Error("Class not found: " + implName +
":\ncheck property " + prop +
--- a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java Fri May 06 06:23:30 2016 -0700
@@ -94,7 +94,7 @@
}
private static final String nl =
- GetPropertyAction.getProperty("line.separator");
+ GetPropertyAction.privilegedGetProperty("line.separator");
/**
* Returns a multi-line string containing the description of the syntax
--- a/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -167,6 +167,19 @@
return Nodes.doubleBuilder(exactSizeIfKnown);
}
+ private <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper, int opFlags) {
+ return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE, opFlags) {
+ @Override
+ Sink<Double> opWrapSink(int flags, Sink<U> sink) {
+ return new Sink.ChainedDouble<U>(sink) {
+ @Override
+ public void accept(double t) {
+ downstream.accept(mapper.apply(t));
+ }
+ };
+ }
+ };
+ }
// DoubleStream
@@ -184,7 +197,7 @@
@Override
public final Stream<Double> boxed() {
- return mapToObj(Double::valueOf);
+ return mapToObj(Double::valueOf, 0);
}
@Override
@@ -207,18 +220,7 @@
@Override
public final <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
Objects.requireNonNull(mapper);
- return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE,
- StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
- @Override
- Sink<Double> opWrapSink(int flags, Sink<U> sink) {
- return new Sink.ChainedDouble<U>(sink) {
- @Override
- public void accept(double t) {
- downstream.accept(mapper.apply(t));
- }
- };
- }
- };
+ return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
}
@Override
--- a/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -170,6 +170,19 @@
return Nodes.intBuilder(exactSizeIfKnown);
}
+ private <U> Stream<U> mapToObj(IntFunction<? extends U> mapper, int opFlags) {
+ return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE, opFlags) {
+ @Override
+ Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
+ return new Sink.ChainedInt<U>(sink) {
+ @Override
+ public void accept(int t) {
+ downstream.accept(mapper.apply(t));
+ }
+ };
+ }
+ };
+ }
// IntStream
@@ -187,8 +200,7 @@
@Override
public final LongStream asLongStream() {
- return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
- StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
+ return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE, 0) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedInt<Long>(sink) {
@@ -203,8 +215,7 @@
@Override
public final DoubleStream asDoubleStream() {
- return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
- StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
+ return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE, 0) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedInt<Double>(sink) {
@@ -219,7 +230,7 @@
@Override
public final Stream<Integer> boxed() {
- return mapToObj(Integer::valueOf);
+ return mapToObj(Integer::valueOf, 0);
}
@Override
@@ -242,18 +253,7 @@
@Override
public final <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
Objects.requireNonNull(mapper);
- return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE,
- StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
- @Override
- Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
- return new Sink.ChainedInt<U>(sink) {
- @Override
- public void accept(int t) {
- downstream.accept(mapper.apply(t));
- }
- };
- }
- };
+ return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
}
@Override
--- a/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -167,6 +167,19 @@
return Nodes.longBuilder(exactSizeIfKnown);
}
+ private <U> Stream<U> mapToObj(LongFunction<? extends U> mapper, int opFlags) {
+ return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE, opFlags) {
+ @Override
+ Sink<Long> opWrapSink(int flags, Sink<U> sink) {
+ return new Sink.ChainedLong<U>(sink) {
+ @Override
+ public void accept(long t) {
+ downstream.accept(mapper.apply(t));
+ }
+ };
+ }
+ };
+ }
// LongStream
@@ -184,8 +197,7 @@
@Override
public final DoubleStream asDoubleStream() {
- return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
- StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
+ return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedLong<Double>(sink) {
@@ -200,7 +212,7 @@
@Override
public final Stream<Long> boxed() {
- return mapToObj(Long::valueOf);
+ return mapToObj(Long::valueOf, 0);
}
@Override
@@ -223,18 +235,7 @@
@Override
public final <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
Objects.requireNonNull(mapper);
- return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE,
- StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
- @Override
- Sink<Long> opWrapSink(int flags, Sink<U> sink) {
- return new Sink.ChainedLong<U>(sink) {
- @Override
- public void accept(long t) {
- downstream.accept(mapper.apply(t));
- }
- };
- }
- };
+ return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
}
@Override
--- a/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java Fri May 06 06:23:30 2016 -0700
@@ -28,6 +28,7 @@
import java.util.Objects;
import java.util.Spliterator;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
@@ -905,6 +906,7 @@
// The spliterator to slice
protected final T_SPLITR s;
protected final boolean unlimited;
+ protected final int chunkSize;
private final long skipThreshold;
private final AtomicLong permits;
@@ -912,6 +914,8 @@
this.s = s;
this.unlimited = limit < 0;
this.skipThreshold = limit >= 0 ? limit : 0;
+ this.chunkSize = limit >= 0 ? (int)Math.min(CHUNK_SIZE,
+ ((skip + limit) / AbstractTask.LEAF_TARGET) + 1) : CHUNK_SIZE;
this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
}
@@ -921,6 +925,7 @@
this.unlimited = parent.unlimited;
this.permits = parent.permits;
this.skipThreshold = parent.skipThreshold;
+ this.chunkSize = parent.chunkSize;
}
/**
@@ -1029,13 +1034,13 @@
PermitStatus permitStatus;
while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
if (permitStatus == PermitStatus.MAYBE_MORE) {
- // Optimistically traverse elements up to a threshold of CHUNK_SIZE
+ // Optimistically traverse elements up to a threshold of chunkSize
if (sb == null)
- sb = new ArrayBuffer.OfRef<>(CHUNK_SIZE);
+ sb = new ArrayBuffer.OfRef<>(chunkSize);
else
sb.reset();
long permitsRequested = 0;
- do { } while (s.tryAdvance(sb) && ++permitsRequested < CHUNK_SIZE);
+ do { } while (s.tryAdvance(sb) && ++permitsRequested < chunkSize);
if (permitsRequested == 0)
return;
sb.forEach(action, acquirePermits(permitsRequested));
@@ -1102,15 +1107,15 @@
PermitStatus permitStatus;
while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
if (permitStatus == PermitStatus.MAYBE_MORE) {
- // Optimistically traverse elements up to a threshold of CHUNK_SIZE
+ // Optimistically traverse elements up to a threshold of chunkSize
if (sb == null)
- sb = bufferCreate(CHUNK_SIZE);
+ sb = bufferCreate(chunkSize);
else
sb.reset();
@SuppressWarnings("unchecked")
T_CONS sbc = (T_CONS) sb;
long permitsRequested = 0;
- do { } while (s.tryAdvance(sbc) && ++permitsRequested < CHUNK_SIZE);
+ do { } while (s.tryAdvance(sbc) && ++permitsRequested < chunkSize);
if (permitsRequested == 0)
return;
sb.forEach(action, acquirePermits(permitsRequested));
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Fri May 06 06:23:30 2016 -0700
@@ -55,7 +55,7 @@
*/
private static final boolean inhibitZip64 =
Boolean.parseBoolean(
- GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64"));
+ GetPropertyAction.privilegedGetProperty("jdk.util.zip.inhibitZip64"));
private static class XEntry {
final ZipEntry entry;
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java Fri May 06 06:23:30 2016 -0700
@@ -97,6 +97,7 @@
}
}
log("class " + clsName + " is loaded");
+ @SuppressWarnings("deprecation")
SSLServerSocketFactory fac = (SSLServerSocketFactory)cls.newInstance();
log("instantiated an instance of class " + clsName);
theFactory = fac;
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Fri May 06 06:23:30 2016 -0700
@@ -51,7 +51,7 @@
static final boolean DEBUG;
static {
- String s = GetPropertyAction.getProperty("javax.net.debug", "")
+ String s = GetPropertyAction.privilegedGetProperty("javax.net.debug", "")
.toLowerCase(Locale.ENGLISH);
DEBUG = s.contains("all") || s.contains("ssl");
@@ -106,6 +106,7 @@
}
}
log("class " + clsName + " is loaded");
+ @SuppressWarnings("deprecation")
SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance();
log("instantiated an instance of class " + clsName);
theFactory = fac;
--- a/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java Fri May 06 06:23:30 2016 -0700
@@ -250,7 +250,9 @@
finalClass, false,
Thread.currentThread().getContextClassLoader()
).asSubclass(Configuration.class);
- return implClass.newInstance();
+ @SuppressWarnings("deprecation")
+ Configuration result = implClass.newInstance();
+ return result;
}
});
AccessController.doPrivileged(
--- a/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java Fri May 06 06:23:30 2016 -0700
@@ -304,7 +304,9 @@
Class<? extends CallbackHandler> c = Class.forName(
defaultHandler, true,
finalLoader).asSubclass(CallbackHandler.class);
- return c.newInstance();
+ @SuppressWarnings("deprecation")
+ CallbackHandler result = c.newInstance();
+ return result;
}
});
} catch (java.security.PrivilegedActionException pae) {
@@ -697,8 +699,9 @@
if (moduleStack[i].module == null) {
try {
- moduleStack[i].module = (LoginModule) Class.forName(
- name, false, contextClassLoader).newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(name, false, contextClassLoader).newInstance();
+ moduleStack[i].module = (LoginModule) tmp;
if (debug != null) {
debug.println(name + " loaded via reflection");
}
--- a/jdk/src/java.base/share/classes/jdk/Version.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/Version.java Fri May 06 06:23:30 2016 -0700
@@ -273,7 +273,8 @@
*/
public static Version current() {
if (current == null) {
- current = parse(GetPropertyAction.getProperty("java.version"));
+ current = parse(
+ GetPropertyAction.privilegedGetProperty("java.version"));
}
return current;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java Fri May 06 06:23:30 2016 -0700
@@ -124,7 +124,9 @@
ClassLoader cl = newJrtFsLoader(jrtfs);
try {
Class<?> c = Class.forName(JrtFileSystemProvider.class.getName(), false, cl);
- return ((FileSystemProvider)c.newInstance()).newFileSystem(uri, newEnv);
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ return ((FileSystemProvider)tmp).newFileSystem(uri, newEnv);
} catch (ClassNotFoundException |
IllegalAccessException |
InstantiationException e) {
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -68,7 +68,7 @@
}
// ServiceCatalog for the boot class loader
- private static final ServicesCatalog SERVICES_CATALOG = new ServicesCatalog();
+ private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create();
// ClassLoaderValue map for boot class loader
private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP =
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Fri May 06 06:23:30 2016 -0700
@@ -104,7 +104,7 @@
* A module defined/loaded by a built-in class loader.
*
* A LoadedModule encapsulates a ModuleReference along with its CodeSource
- * URL to avoid needing to create this URL when define classes.
+ * URL to avoid needing to create this URL when defining classes.
*/
private static class LoadedModule {
private final BuiltinClassLoader loader;
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Fri May 06 06:23:30 2016 -0700
@@ -85,7 +85,7 @@
private static final boolean DISABLE_JAR_CHECKING;
static {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
JAVA_VERSION = props.getProperty("java.version");
DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null);
String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking");
@@ -372,9 +372,15 @@
return java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<>() {
public Loader run() throws IOException {
+ String protocol = url.getProtocol(); // lower cased in URL
String file = url.getFile();
- if (file != null && file.endsWith("/")) {
- if ("file".equals(url.getProtocol())) {
+ if ("jar".equals(protocol)
+ && file != null && (file.indexOf("!/") == file.length() - 2)) {
+ // extract the nested URL
+ URL nestedUrl = new URL(file.substring(0, file.length() - 2));
+ return new JarLoader(nestedUrl, jarHandler, lmap);
+ } else if (file != null && file.endsWith("/")) {
+ if ("file".equals(protocol)) {
return new FileLoader(url);
} else {
return new Loader(url);
@@ -718,13 +724,13 @@
final URL url;
try {
+ String nm;
if (jar.isMultiRelease()) {
- // add #runtime fragment to tell JarURLConnection to use
- // runtime versioning if the underlying jar file is multi-release
- url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime");
+ nm = SharedSecrets.javaUtilJarAccess().getRealName(jar, entry);
} else {
- url = new URL(getBaseURL(), ParseUtil.encodePath(name, false));
+ nm = name;
}
+ url = new URL(getBaseURL(), ParseUtil.encodePath(nm, false));
if (check) {
URLClassPath.check(url);
}
@@ -940,7 +946,8 @@
ensureOpen();
- if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { // Only get manifest when necessary
+ // Only get manifest when necessary
+ if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) {
Manifest man = jar.getManifest();
if (man != null) {
Attributes attr = man.getMainAttributes();
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java Fri May 06 06:23:30 2016 -0700
@@ -81,7 +81,7 @@
// Get configuration error policy
private static ErrorPolicy configurationErrorPolicy() {
String errorPolicy =
- GetPropertyAction.getProperty("jdk.logger.finder.error");
+ GetPropertyAction.privilegedGetProperty("jdk.logger.finder.error");
if (errorPolicy == null || errorPolicy.isEmpty()) {
return ErrorPolicy.WARNING;
}
@@ -96,7 +96,7 @@
// This is further submitted to the configuration error policy.
private static boolean ensureSingletonProvider() {
return Boolean.parseBoolean(
- GetPropertyAction.getProperty("jdk.logger.finder.singleton"));
+ GetPropertyAction.privilegedGetProperty("jdk.logger.finder.singleton"));
}
private static Iterator<System.LoggerFinder> findLoggerFinderProviders() {
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Fri May 06 06:23:30 2016 -0700
@@ -56,7 +56,7 @@
static Level getDefaultLevel() {
String levelName = GetPropertyAction
- .getProperty("jdk.system.logger.level", "INFO");
+ .privilegedGetProperty("jdk.system.logger.level", "INFO");
try {
return Level.valueOf(levelName);
} catch (IllegalArgumentException iae) {
@@ -426,7 +426,7 @@
static private final String[] skips;
static {
String additionalPkgs =
- GetPropertyAction.getProperty("jdk.logger.packages");
+ GetPropertyAction.privilegedGetProperty("jdk.logger.packages");
skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(",");
}
@@ -485,7 +485,7 @@
// jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
// to fail - because that test has a testcase which somehow references
// PlatformLogger and counts the number of generated lambda classes.
- String format = GetPropertyAction.getProperty(key);
+ String format = GetPropertyAction.privilegedGetProperty(key);
if (format == null && defaultPropertyGetter != null) {
format = defaultPropertyGetter.apply(key);
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -25,13 +25,24 @@
package jdk.internal.misc;
+import java.io.PrintStream;
+import java.lang.module.Configuration;
+import jdk.internal.module.ModuleHashes;
+
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Version;
+import java.lang.module.ModuleFinder;
+import java.util.Collection;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.function.Supplier;
/**
* Provides access to non-public methods in java.lang.module.
@@ -89,5 +100,29 @@
String osArch,
String osVersion,
Set<String> conceals,
- Set<String> packages);
+ Set<String> packages,
+ ModuleHashes hashes);
+
+ /**
+ * Resolves a collection of root modules, with service binding
+ * and the empty configuration as the parent. The post resolution
+ * checks are optionally run.
+ */
+ Configuration resolveRequiresAndUses(ModuleFinder finder,
+ Collection<String> roots,
+ boolean check,
+ PrintStream traceOutput);
+
+ /**
+ * Creates a ModuleReference to a "patched" module.
+ */
+ ModuleReference newPatchedModule(ModuleDescriptor descriptor,
+ URI location,
+ Supplier<ModuleReader> readerSupplier);
+
+ /**
+ * Returns the object with the hashes of other modules
+ */
+ Optional<ModuleHashes> hashes(ModuleDescriptor descriptor);
+
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,12 @@
package jdk.internal.misc;
import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Layer;
import java.lang.reflect.Module;
import java.net.URI;
+import jdk.internal.module.ServicesCatalog;
+
/**
* Provides access to non-public methods in java.lang.reflect.Module
*/
@@ -57,6 +60,11 @@
void addReads(Module m1, Module m2);
/**
+ * Updates module m to read all unnamed modules.
+ */
+ void addReadsAllUnnamed(Module m);
+
+ /**
* Updates module m1 to export a package to module m2. The export does
* not result in a strong reference to m2 (m2 can be GC'ed).
*/
@@ -76,4 +84,10 @@
* Add a package to the given module.
*/
void addPackage(Module m, String pkg);
-}
+
+ /**
+ * Returns the ServicesCatalog for the given Layer.
+ */
+ ServicesCatalog getServicesCatalog(Layer layer);
+
+}
\ No newline at end of file
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java Fri May 06 06:23:30 2016 -0700
@@ -41,4 +41,5 @@
public Enumeration<JarEntry> entries2(JarFile jar);
public void setEagerValidation(JarFile jar, boolean eager);
public List<Object> getManifestDigests(JarFile jar);
+ public String getRealName(JarFile jar, JarEntry entry);
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java Fri May 06 06:23:30 2016 -0700
@@ -74,6 +74,8 @@
String osName;
String osArch;
String osVersion;
+ String algorithm;
+ Map<String, String> hashes;
Builder(String name, int reqs, int exports,
int provides, int conceals, int packages) {
@@ -252,6 +254,25 @@
}
/**
+ * Sets the algorithm of the module hashes
+ */
+ public Builder algorithm(String algorithm) {
+ this.algorithm = algorithm;
+ return this;
+ }
+
+ /**
+ * Sets the module hash for the given module name
+ */
+ public Builder moduleHash(String mn, String hash) {
+ if (hashes == null)
+ hashes = new HashMap<>();
+
+ hashes.put(mn, hash);
+ return this;
+ }
+
+ /**
* Returns the set of packages that is the union of the exported and
* concealed packages.
*/
@@ -273,6 +294,9 @@
public ModuleDescriptor build() {
assert name != null;
+ ModuleHashes moduleHashes =
+ hashes != null ? new ModuleHashes(algorithm, hashes) : null;
+
return jlma.newModuleDescriptor(name,
false, // automatic
false, // assume not synthetic for now
@@ -286,6 +310,7 @@
osArch,
osVersion,
conceals,
- computePackages(exports, conceals));
+ computePackages(exports, conceals),
+ moduleHashes);
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Fri May 06 06:23:30 2016 -0700
@@ -34,6 +34,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@@ -42,7 +43,6 @@
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.module.Hasher.DependencyHashes;
import static jdk.internal.module.ClassFileConstants.*;
@@ -148,7 +148,7 @@
for (int i=0; i<provides_count; i++) {
String sn = cr.readClass(off, buf).replace('/', '.');
String cn = cr.readClass(off + 2, buf).replace('/', '.');
- provides.computeIfAbsent(sn, k -> new HashSet<>()).add(cn);
+ provides.computeIfAbsent(sn, k -> new LinkedHashSet<>()).add(cn);
off += 4;
}
provides.entrySet().forEach(e -> builder.provides(e.getKey(),
@@ -281,10 +281,10 @@
* u4 attribute_length;
*
* // the number of entries in the packages table
- * u2 package_count;
+ * u2 packages_count;
* { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
* u2 package_index
- * } package[package_count];
+ * } packages[package_count];
*
* }</pre>
*/
@@ -579,9 +579,9 @@
* alternative is to store it as an array of u1.
*/
static class HashesAttribute extends Attribute {
- private final DependencyHashes hashes;
+ private final ModuleHashes hashes;
- HashesAttribute(DependencyHashes hashes) {
+ HashesAttribute(ModuleHashes hashes) {
super(HASHES);
this.hashes = hashes;
}
@@ -613,7 +613,7 @@
map.put(dn, hash);
}
- DependencyHashes hashes = new DependencyHashes(algorithm, map);
+ ModuleHashes hashes = new ModuleHashes(algorithm, map);
return new HashesAttribute(hashes);
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.module;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.Path;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Supporting class for computing, encoding and decoding hashes (message
- * digests).
- */
-
-public class Hasher {
- private Hasher() { }
-
- /**
- * A supplier of an encoded message digest.
- */
- public static interface HashSupplier {
- String generate(String algorithm);
- }
-
- /**
- * Encapsulates the result of hashing the contents of a number of module
- * artifacts.
- */
- public static class DependencyHashes {
- private final String algorithm;
- private final Map<String, String> nameToHash;
-
- public DependencyHashes(String algorithm, Map<String, String> nameToHash) {
- this.algorithm = algorithm;
- this.nameToHash = nameToHash;
- }
-
- /**
- * Returns the algorithm used to hash the dependences ("SHA-256" or
- * "MD5" for example).
- */
- public String algorithm() {
- return algorithm;
- }
-
- /**
- * Returns the set of module names for which hashes are recorded.
- */
- public Set<String> names() {
- return nameToHash.keySet();
- }
-
- /**
- * Retruns the hash string for the given module name, {@code null}
- * if there is no hash recorded for the module.
- */
- public String hashFor(String dn) {
- return nameToHash.get(dn);
- }
- }
-
-
- /**
- * Computes the hash for the given file with the given message digest
- * algorithm. Returns the results a base64-encoded String.
- *
- * @throws UncheckedIOException if an I/O error occurs
- * @throws RuntimeException if the algorithm is not available
- */
- public static String generate(Path file, String algorithm) {
- try {
- MessageDigest md = MessageDigest.getInstance(algorithm);
-
- // Ideally we would just mmap the file but this consumes too much
- // memory when jlink is running concurrently on very large jmods
- try (FileChannel fc = FileChannel.open(file)) {
- ByteBuffer bb = ByteBuffer.allocate(32*1024);
- int nread;
- while ((nread = fc.read(bb)) > 0) {
- bb.flip();
- md.update(bb);
- assert bb.remaining() == 0;
- bb.clear();
- }
- }
-
- byte[] bytes = md.digest();
- return Base64.getEncoder().encodeToString(bytes);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
- } catch (IOException ioe) {
- throw new UncheckedIOException(ioe);
- }
- }
-
- /**
- * Computes the hash for every entry in the given map, returning a
- * {@code DependencyHashes} to encapsulate the result. The map key is
- * the entry name, typically the module name. The map value is the file
- * path to the entry (module artifact).
- *
- * @return DependencyHashes encapsulate the hashes
- */
- public static DependencyHashes generate(Map<String, Path> map, String algorithm) {
- Map<String, String> nameToHash = new HashMap<>();
- for (Map.Entry<String, Path> entry: map.entrySet()) {
- String name = entry.getKey();
- Path path = entry.getValue();
- nameToHash.put(name, generate(path, algorithm));
- }
- return new DependencyHashes(algorithm, nameToHash);
- }
-}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Fri May 06 06:23:30 2016 -0700
@@ -26,12 +26,15 @@
package jdk.internal.module;
import java.io.File;
+import java.io.PrintStream;
import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
-import java.lang.module.ModuleFinder;
import java.lang.module.ResolvedModule;
import java.lang.reflect.Layer;
import java.lang.reflect.Module;
+import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
@@ -41,10 +44,10 @@
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
-import java.util.stream.Collectors;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.misc.SharedSecrets;
import jdk.internal.perf.PerfCounter;
/**
@@ -54,10 +57,9 @@
* the module system. In summary, the boot method creates a Configuration by
* resolving a set of module names specified via the launcher (or equivalent)
* -m and -addmods options. The modules are located on a module path that is
- * constructed from the upgrade, system and application module paths. The
- * Configuration is reified by creating the boot Layer with each module in the
- * the configuration defined to one of the built-in class loaders. The mapping
- * of modules to class loaders is statically mapped in a helper class.
+ * constructed from the upgrade module path, system modules, and application
+ * module path. The Configuration is instantiated as the boot Layer with each
+ * module in the the configuration defined to one of the built-in class loaders.
*/
public final class ModuleBootstrap {
@@ -65,6 +67,11 @@
private static final String JAVA_BASE = "java.base";
+ private static final String JAVA_SE = "java.se";
+
+ // the token for "all default modules"
+ private static final String ALL_DEFAULT = "ALL-DEFAULT";
+
// the token for "all unnamed modules"
private static final String ALL_UNNAMED = "ALL-UNNAMED";
@@ -94,47 +101,65 @@
long t0 = System.nanoTime();
- // system module path
- ModuleFinder systemModulePath = ModuleFinder.ofSystem();
+ // system modules
+ ModuleFinder systemModules = ModuleFinder.ofSystem();
+
+ PerfCounters.systemModulesTime.addElapsedTimeFrom(t0);
- // Once we have the system module path then we define the base module.
- // We do this here so that java.base is defined to the VM as early as
+
+ long t1 = System.nanoTime();
+
+ // Once we have the system modules then we define the base module to
+ // the VM. We do this here so that java.base is defined as early as
// possible and also that resources in the base module can be located
// for error messages that may happen from here on.
- Optional<ModuleReference> obase = systemModulePath.find(JAVA_BASE);
- if (!obase.isPresent())
+ ModuleReference base = systemModules.find(JAVA_BASE).orElse(null);
+ if (base == null)
throw new InternalError(JAVA_BASE + " not found");
- ModuleReference base = obase.get();
+ URI baseUri = base.location().orElse(null);
+ if (baseUri == null)
+ throw new InternalError(JAVA_BASE + " does not have a location");
BootLoader.loadModule(base);
- Modules.defineModule(null, base.descriptor(), base.location().orElse(null));
+ Modules.defineModule(null, base.descriptor(), baseUri);
+ PerfCounters.defineBaseTime.addElapsedTimeFrom(t1);
+
+
+ long t2 = System.nanoTime();
// -upgrademodulepath option specified to launcher
ModuleFinder upgradeModulePath
= createModulePathFinder("jdk.upgrade.module.path");
+ if (upgradeModulePath != null)
+ systemModules = ModuleFinder.compose(upgradeModulePath, systemModules);
// -modulepath option specified to the launcher
ModuleFinder appModulePath = createModulePathFinder("jdk.module.path");
- // The module finder: [-upgrademodulepath] system-module-path [-modulepath]
- ModuleFinder finder = systemModulePath;
- if (upgradeModulePath != null)
- finder = ModuleFinder.compose(upgradeModulePath, finder);
+ // The module finder: [-upgrademodulepath] system [-modulepath]
+ ModuleFinder finder = systemModules;
if (appModulePath != null)
finder = ModuleFinder.compose(finder, appModulePath);
- // launcher -m option to specify the initial module
+ // The root modules to resolve
+ Set<String> roots = new HashSet<>();
+
+ // launcher -m option to specify the main/initial module
String mainModule = System.getProperty("jdk.module.main");
+ if (mainModule != null)
+ roots.add(mainModule);
// additional module(s) specified by -addmods
+ boolean addAllDefaultModules = false;
boolean addAllSystemModules = false;
boolean addAllApplicationModules = false;
- Set<String> addModules = null;
String propValue = System.getProperty("jdk.launcher.addmods");
if (propValue != null) {
- addModules = new HashSet<>();
for (String mod: propValue.split(",")) {
switch (mod) {
+ case ALL_DEFAULT:
+ addAllDefaultModules = true;
+ break;
case ALL_SYSTEM:
addAllSystemModules = true;
break;
@@ -142,28 +167,12 @@
addAllApplicationModules = true;
break;
default :
- addModules.add(mod);
+ roots.add(mod);
}
}
}
- // The root modules to resolve
- Set<String> roots = new HashSet<>();
-
- // main/initial module
- if (mainModule != null) {
- roots.add(mainModule);
- if (addAllApplicationModules)
- fail(ALL_MODULE_PATH + " not allowed with initial module");
- }
-
- // If -addmods is specified then those modules need to be resolved
- if (addModules != null)
- roots.addAll(addModules);
-
-
// -limitmods
- boolean limitmods = false;
propValue = System.getProperty("jdk.launcher.limitmods");
if (propValue != null) {
Set<String> mods = new HashSet<>();
@@ -171,62 +180,101 @@
mods.add(mod);
}
finder = limitFinder(finder, mods, roots);
- limitmods = true;
}
-
- // If there is no initial module specified then assume that the
- // initial module is the unnamed module of the application class
- // loader. By convention, and for compatibility, this is
- // implemented by putting the names of all modules on the system
- // module path into the set of modules to resolve.
- //
- // If `-addmods ALL-SYSTEM` is used then all modules on the system
- // module path will be resolved, irrespective of whether an initial
- // module is specified.
- //
- // If `-addmods ALL-MODULE-PATH` is used, and no initial module is
- // specified, then all modules on the application module path will
- // be resolved.
- //
- if (mainModule == null || addAllSystemModules) {
- Set<ModuleReference> mrefs;
- if (addAllApplicationModules) {
- assert mainModule == null;
- mrefs = finder.findAll();
- } else {
- mrefs = systemModulePath.findAll();
- if (limitmods) {
- ModuleFinder f = finder;
- mrefs = mrefs.stream()
- .filter(m -> f.find(m.descriptor().name()).isPresent())
- .collect(Collectors.toSet());
+ // If there is no initial module specified then assume that the initial
+ // module is the unnamed module of the application class loader. This
+ // is implemented by resolving "java.se" and all (non-java.*) modules
+ // that export an API. If "java.se" is not observable then all java.*
+ // modules are resolved.
+ if (mainModule == null || addAllDefaultModules) {
+ boolean hasJava = false;
+ if (systemModules.find(JAVA_SE).isPresent()) {
+ // java.se is a system module
+ if (finder == systemModules || finder.find(JAVA_SE).isPresent()) {
+ // java.se is observable
+ hasJava = true;
+ roots.add(JAVA_SE);
}
}
- // map to module names
- for (ModuleReference mref : mrefs) {
- roots.add(mref.descriptor().name());
+
+ for (ModuleReference mref : systemModules.findAll()) {
+ String mn = mref.descriptor().name();
+ if (hasJava && mn.startsWith("java."))
+ continue;
+
+ // add as root if observable and exports at least one package
+ if ((finder == systemModules || finder.find(mn).isPresent())) {
+ ModuleDescriptor descriptor = mref.descriptor();
+ for (ModuleDescriptor.Exports e : descriptor.exports()) {
+ if (!e.isQualified()) {
+ roots.add(mn);
+ break;
+ }
+ }
+ }
}
}
- long t1 = System.nanoTime();
+ // If `-addmods ALL-SYSTEM` is specified then all observable system
+ // modules will be resolved.
+ if (addAllSystemModules) {
+ ModuleFinder f = finder; // observable modules
+ systemModules.findAll()
+ .stream()
+ .map(ModuleReference::descriptor)
+ .map(ModuleDescriptor::name)
+ .filter(mn -> f.find(mn).isPresent()) // observable
+ .forEach(mn -> roots.add(mn));
+ }
+
+ // If `-addmods ALL-MODULE-PATH` is specified then all observable
+ // modules on the application module path will be resolved.
+ if (appModulePath != null && addAllApplicationModules) {
+ ModuleFinder f = finder; // observable modules
+ appModulePath.findAll()
+ .stream()
+ .map(ModuleReference::descriptor)
+ .map(ModuleDescriptor::name)
+ .filter(mn -> f.find(mn).isPresent()) // observable
+ .forEach(mn -> roots.add(mn));
+ }
+
+ PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2);
+
+
+ long t3 = System.nanoTime();
+
+ // determine if post resolution checks are needed
+ boolean needPostResolutionChecks = true;
+ if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here
+ && (upgradeModulePath == null)
+ && (appModulePath == null)
+ && (System.getProperty("jdk.launcher.patch.0") == null)) {
+ needPostResolutionChecks = false;
+ }
+
+ PrintStream traceOutput = null;
+ if (Boolean.getBoolean("jdk.launcher.traceResolver"))
+ traceOutput = System.out;
// run the resolver to create the configuration
-
- Configuration cf = Configuration.empty()
+ Configuration cf = SharedSecrets.getJavaLangModuleAccess()
.resolveRequiresAndUses(finder,
- ModuleFinder.empty(),
- roots);
+ roots,
+ needPostResolutionChecks,
+ traceOutput);
// time to create configuration
- PerfCounters.resolveTime.addElapsedTimeFrom(t1);
+ PerfCounters.resolveTime.addElapsedTimeFrom(t3);
+
// mapping of modules to class loaders
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
// check that all modules to be mapped to the boot loader will be
- // loaded from the system module path
- if (finder != systemModulePath) {
+ // loaded from the runtime image
+ if (needPostResolutionChecks) {
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
String name = mref.descriptor().name();
@@ -237,20 +285,22 @@
&& upgradeModulePath.find(name).isPresent())
fail(name + ": cannot be loaded from upgrade module path");
- if (!systemModulePath.find(name).isPresent())
+ if (!systemModules.find(name).isPresent())
fail(name + ": cannot be loaded from application module path");
}
}
}
- long t2 = System.nanoTime();
+
+ long t4 = System.nanoTime();
// define modules to VM/runtime
Layer bootLayer = Layer.empty().defineModules(cf, clf);
- PerfCounters.layerCreateTime.addElapsedTimeFrom(t2);
+ PerfCounters.layerCreateTime.addElapsedTimeFrom(t4);
- long t3 = System.nanoTime();
+
+ long t5 = System.nanoTime();
// define the module to its class loader, except java.base
for (ResolvedModule resolvedModule : cf.modules()) {
@@ -264,7 +314,8 @@
}
}
- PerfCounters.loadModulesTime.addElapsedTimeFrom(t3);
+ PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
+
// -XaddReads and -XaddExports
addExtraReads(bootLayer);
@@ -295,25 +346,21 @@
// module name -> reference
Map<String, ModuleReference> map = new HashMap<>();
+
+ // root modules and their transitive dependences
cf.modules().stream()
.map(ResolvedModule::reference)
.forEach(mref -> map.put(mref.descriptor().name(), mref));
+ // additional modules
+ otherMods.stream()
+ .map(finder::find)
+ .flatMap(Optional::stream)
+ .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref));
+
// set of modules that are observable
Set<ModuleReference> mrefs = new HashSet<>(map.values());
- // add the other modules
- for (String mod : otherMods) {
- Optional<ModuleReference> omref = finder.find(mod);
- if (omref.isPresent()) {
- ModuleReference mref = omref.get();
- map.putIfAbsent(mod, mref);
- mrefs.add(mref);
- } else {
- // no need to fail
- }
- }
-
return new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
@@ -369,15 +416,15 @@
Module other;
if (ALL_UNNAMED.equals(name)) {
- other = null; // loose
+ Modules.addReadsAllUnnamed(m);
} else {
om = bootLayer.findModule(name);
if (!om.isPresent())
fail("Unknown module: " + name);
other = om.get();
+ Modules.addReads(m, other);
}
- Modules.addReads(m, other);
}
}
}
@@ -439,10 +486,6 @@
* Decodes the values of -XaddReads or -XaddExports options
*
* The format of the options is: $KEY=$MODULE(,$MODULE)*
- *
- * For transition purposes, this method allows the first usage to be
- * $KEY=$MODULE(,$KEY=$MODULE)
- * This format will eventually be removed.
*/
private static Map<String, Set<String>> decode(String prefix) {
int index = 0;
@@ -467,42 +510,15 @@
if (rhs.isEmpty())
fail("Unable to parse: " + value);
- // new format $MODULE(,$MODULE)* or old format $(MODULE)=...
- pos = rhs.indexOf('=');
- // old format only allowed in first -X option
- if (pos >= 0 && index > 0)
- fail("Unable to parse: " + value);
-
- if (pos == -1) {
-
- // new format: $KEY=$MODULE(,$MODULE)*
-
- Set<String> values = map.get(key);
- if (values != null)
- fail(key + " specified more than once");
+ // value is <module>(,<module>)*
+ if (map.containsKey(key))
+ fail(key + " specified more than once");
- values = new HashSet<>();
- map.put(key, values);
- for (String s : rhs.split(",")) {
- if (s.length() > 0) values.add(s);
- }
-
- } else {
-
- // old format: $KEY=$MODULE(,$KEY=$MODULE)*
-
- assert index == 0; // old format only allowed in first usage
-
- for (String expr : value.split(",")) {
- if (expr.length() > 0) {
- String[] s = expr.split("=");
- if (s.length != 2)
- fail("Unable to parse: " + expr);
-
- map.computeIfAbsent(s[0], k -> new HashSet<>()).add(s[1]);
- }
- }
+ Set<String> values = new HashSet<>();
+ map.put(key, values);
+ for (String s : rhs.split(",")) {
+ if (s.length() > 0) values.add(s);
}
index++;
@@ -521,6 +537,13 @@
}
static class PerfCounters {
+
+ static PerfCounter systemModulesTime
+ = PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime");
+ static PerfCounter defineBaseTime
+ = PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime");
+ static PerfCounter optionsAndRootsTime
+ = PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime");
static PerfCounter resolveTime
= PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime");
static PerfCounter layerCreateTime
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * 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.internal.module;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The result of hashing the contents of a number of module artifacts.
+ */
+
+public final class ModuleHashes {
+
+ /**
+ * A supplier of an encoded message digest.
+ */
+ public static interface HashSupplier {
+ String generate(String algorithm);
+ }
+
+
+ private final String algorithm;
+ private final Map<String, String> nameToHash;
+
+ /**
+ * Creates a {@code ModuleHashes}.
+ *
+ * @param algorithm the algorithm used to create the hashes
+ * @param nameToHash the map of module name to hash value (in string form)
+ */
+ public ModuleHashes(String algorithm, Map<String, String> nameToHash) {
+ this.algorithm = algorithm;
+ this.nameToHash = Collections.unmodifiableMap(nameToHash);
+ }
+
+ /**
+ * Returns the algorithm used to hash the modules ("SHA-256" for example).
+ */
+ public String algorithm() {
+ return algorithm;
+ }
+
+ /**
+ * Returns the set of module names for which hashes are recorded.
+ */
+ public Set<String> names() {
+ return nameToHash.keySet();
+ }
+
+ /**
+ * Returns the hash string for the given module name, {@code null}
+ * if there is no hash recorded for the module.
+ */
+ public String hashFor(String mn) {
+ return nameToHash.get(mn);
+ }
+
+ /**
+ * Returns unmodifiable map of module name to hash string.
+ */
+ public Map<String, String> hashes() {
+ return nameToHash;
+ }
+
+ /**
+ * Computes the hash for the given file with the given message digest
+ * algorithm. Returns the results a base64-encoded String.
+ *
+ * @throws UncheckedIOException if an I/O error occurs
+ * @throws RuntimeException if the algorithm is not available
+ */
+ public static String computeHashAsString(Path file, String algorithm) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+
+ // Ideally we would just mmap the file but this consumes too much
+ // memory when jlink is running concurrently on very large jmods
+ try (FileChannel fc = FileChannel.open(file)) {
+ ByteBuffer bb = ByteBuffer.allocate(32*1024);
+ while (fc.read(bb) > 0) {
+ bb.flip();
+ md.update(bb);
+ assert bb.remaining() == 0;
+ bb.clear();
+ }
+ }
+
+ byte[] bytes = md.digest();
+ return Base64.getEncoder().encodeToString(bytes);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
+ }
+ }
+
+ /**
+ * Computes the hash for every entry in the given map, returning a
+ * {@code ModuleHashes} to encapsulate the result. The map key is
+ * the entry name, typically the module name. The map value is the file
+ * path to the entry (module artifact).
+ *
+ * @return ModuleHashes encapsulate the hashes
+ */
+ public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
+ Map<String, String> nameToHash = new HashMap<>();
+ for (Map.Entry<String, Path> entry: map.entrySet()) {
+ String name = entry.getKey();
+ Path path = entry.getValue();
+ nameToHash.put(name, computeHashAsString(path, algorithm));
+ }
+ return new ModuleHashes(algorithm, nameToHash);
+ }
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,6 @@
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.module.Hasher.DependencyHashes;
import static jdk.internal.module.ClassFileAttributes.*;
@@ -69,7 +68,7 @@
private String osVersion;
// the hashes for the Hashes attribute
- private DependencyHashes hashes;
+ private ModuleHashes hashes;
private ModuleInfoExtender(InputStream in) {
this.in = in;
@@ -113,10 +112,10 @@
/**
* The Hashes attribute will be emitted to the module-info with
- * the hashes encapsulated in the given {@code DependencyHashes}
+ * the hashes encapsulated in the given {@code ModuleHashes}
* object.
*/
- public ModuleInfoExtender hashes(DependencyHashes hashes) {
+ public ModuleInfoExtender hashes(ModuleHashes hashes) {
this.hashes = hashes;
return this;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -49,28 +49,22 @@
* Writes the given module descriptor to a module-info.class file,
* returning it in a byte array.
*/
- private static byte[] toModuleInfo(ModuleDescriptor descriptor) {
+ private static byte[] toModuleInfo(ModuleDescriptor md) {
ClassWriter cw = new ClassWriter(0);
- String name = descriptor.name().replace('.', '/') + "/module-info";
+ String name = md.name().replace('.', '/') + "/module-info";
cw.visit(Opcodes.V1_8, ACC_MODULE, name, null, null, null);
- cw.visitAttribute(new ModuleAttribute(descriptor));
- cw.visitAttribute(new ConcealedPackagesAttribute(descriptor.conceals()));
-
- Optional<Version> oversion = descriptor.version();
- if (oversion.isPresent())
- cw.visitAttribute(new VersionAttribute(oversion.get()));
-
- Optional<String> omain = descriptor.mainClass();
- if (omain.isPresent())
- cw.visitAttribute(new MainClassAttribute(omain.get()));
+ cw.visitAttribute(new ModuleAttribute(md));
+ cw.visitAttribute(new ConcealedPackagesAttribute(md.conceals()));
+ md.version().ifPresent(v -> cw.visitAttribute(new VersionAttribute(v)));
+ md.mainClass().ifPresent(mc -> cw.visitAttribute(new MainClassAttribute(mc)));
// write the TargetPlatform attribute if have any of OS name/arch/version
- String osName = descriptor.osName().orElse(null);
- String osArch = descriptor.osArch().orElse(null);
- String osVersion = descriptor.osVersion().orElse(null);
+ String osName = md.osName().orElse(null);
+ String osArch = md.osArch().orElse(null);
+ String osVersion = md.osVersion().orElse(null);
if (osName != null || osArch != null || osVersion != null) {
cw.visitAttribute(new TargetPlatformAttribute(osName,
osArch,
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Fri May 06 06:23:30 2016 -0700
@@ -91,56 +91,29 @@
Map<String, List<Path>> map = new HashMap<>();
while (value != null) {
- int pos = value.indexOf('=');
+
+ // <module>=<file>(:<file>)*
- if (pos == -1 && index > 0)
+ int pos = value.indexOf('=');
+ if (pos == -1)
throwIAE("Unable to parse: " + value);
-
if (pos == 0)
throwIAE("Missing module name: " + value);
- if (pos > 0) {
-
- // new format: <module>=<file>(:<file>)*
-
- String mn = value.substring(0, pos);
- List<Path> list = map.get(mn);
- if (list != null)
- throwIAE("Module " + mn + " specified more than once");
- list = new ArrayList<>();
- map.put(mn, list);
-
- String paths = value.substring(pos+1);
- for (String path : paths.split(File.pathSeparator)) {
- if (!path.isEmpty()) {
- list.add(Paths.get(path));
- }
- }
-
- } else {
+ String mn = value.substring(0, pos);
+ List<Path> list = map.get(mn);
+ if (list != null)
+ throwIAE("Module " + mn + " specified more than once");
+ list = new ArrayList<>();
+ map.put(mn, list);
- // old format: <dir>(:<dir>)*
-
- assert index == 0; // old format only allowed in first -Xpatch
-
- String[] dirs = value.split(File.pathSeparator);
- for (String d : dirs) {
- if (d.length() > 0) {
- Path top = Paths.get(d);
- try {
- Files.list(top).forEach(e -> {
- String mn = e.getFileName().toString();
- Path dir = top.resolve(mn);
- map.computeIfAbsent(mn, k -> new ArrayList<>())
- .add(dir);
- });
- } catch (IOException ignore) { }
- }
+ String paths = value.substring(pos+1);
+ for (String path : paths.split(File.pathSeparator)) {
+ if (!path.isEmpty()) {
+ list.add(Paths.get(path));
}
-
}
-
index++;
value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
}
@@ -175,7 +148,8 @@
for (Path file : paths) {
if (Files.isRegularFile(file)) {
- // JAR file
+ // JAR file - do not open as a multi-release JAR as this
+ // is not supported by the boot class loader
try (JarFile jf = new JarFile(file.toFile())) {
jf.stream()
.filter(e -> e.getName().endsWith(".class"))
@@ -209,10 +183,11 @@
descriptor = JLMA.newModuleDescriptor(descriptor, packages);
}
- // return a new module reference
+ // return a module reference to the patched module
URI location = mref.location().orElse(null);
- return new ModuleReference(descriptor, location,
- () -> new PatchedModuleReader(paths, mref));
+ return JLMA.newPatchedModule(descriptor,
+ location,
+ () -> new PatchedModuleReader(paths, mref));
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -58,7 +58,7 @@
* Creates a new Module. The module has the given ModuleDescriptor and
* is defined to the given class loader.
*
- * The resulting Module is in a larva state in that it does not not read
+ * The resulting Module is in a larval state in that it does not not read
* any other module and does not have any exports.
*
* The URI is for information purposes only.
@@ -74,7 +74,7 @@
* Define a new module to the VM. The module has the given set of
* concealed packages and is defined to the given class loader.
*
- * The resulting Module is in a larva state in that it does not not read
+ * The resulting Module is in a larval state in that it does not not read
* any other module and does not have any exports.
*/
public static Module defineModule(ClassLoader loader,
@@ -96,6 +96,13 @@
}
/**
+ * Update module {@code m} to read all unnamed modules.
+ */
+ public static void addReadsAllUnnamed(Module m) {
+ JLRMA.addReadsAllUnnamed(m);
+ }
+
+ /**
* Updates module m1 to export a package to module m2.
* Same as m1.addExports(pkg, m2) but without a caller check.
*/
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,94 +29,105 @@
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Provides;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.ConcurrentHashMap;
/**
- * A services catalog. Each {@code ClassLoader} has an optional {@code
- * ServicesCatalog} for modules that provide services. This is to support
- * ClassLoader centric ServiceLoader.load methods.
+ * A <em>services catalog</em>. Each {@code ClassLoader} and {@code Layer} has
+ * an optional {@code ServicesCatalog} for modules that provide services.
+ *
+ * @see java.util.ServiceLoader
*/
-public class ServicesCatalog {
-
- // use RW locks as register is rare
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
- private final Lock readLock = lock.readLock();
- private final Lock writeLock = lock.writeLock();
+public interface ServicesCatalog {
/**
* Represents a service provider in the services catalog.
*/
- public class ServiceProvider {
+ public final class ServiceProvider {
private final Module module;
private final String providerName;
- ServiceProvider(Module module, String providerName) {
+
+ public ServiceProvider(Module module, String providerName) {
this.module = module;
this.providerName = providerName;
}
+
public Module module() {
return module;
}
+
public String providerName() {
return providerName;
}
- }
- // service providers
- private final Map<String, Set<ServiceProvider>> loaderServices = new HashMap<>();
-
- /**
- * Creates a new module catalog.
- */
- public ServicesCatalog() { }
-
- /**
- * Registers the module in this module catalog.
- */
- public void register(Module m) {
- ModuleDescriptor descriptor = m.getDescriptor();
+ @Override
+ public int hashCode() {
+ return Objects.hash(module, providerName);
+ }
- writeLock.lock();
- try {
- // extend the services map
- for (Provides ps : descriptor.provides().values()) {
- String service = ps.service();
- Set<String> providerNames = ps.providers();
-
- // create a new set to replace the existing
- Set<ServiceProvider> result = new HashSet<>();
- Set<ServiceProvider> providers = loaderServices.get(service);
- if (providers != null) {
- result.addAll(providers);
- }
- for (String pn : providerNames) {
- result.add(new ServiceProvider(m, pn));
- }
- loaderServices.put(service, Collections.unmodifiableSet(result));
- }
-
- } finally {
- writeLock.unlock();
+ @Override
+ public boolean equals(Object ob) {
+ if (!(ob instanceof ServiceProvider))
+ return false;
+ ServiceProvider that = (ServiceProvider)ob;
+ return Objects.equals(this.module, that.module)
+ && Objects.equals(this.providerName, that.providerName);
}
}
/**
+ * Registers the providers in the given module in this services catalog.
+ *
+ * @throws UnsupportedOperationException
+ * If this services catalog is immutable
+ */
+ void register(Module module);
+
+ /**
* Returns the (possibly empty) set of service providers that implement the
* given service type.
- *
- * @see java.util.ServiceLoader
+ */
+ Set<ServiceProvider> findServices(String service);
+
+ /**
+ * Creates a ServicesCatalog that supports concurrent registration and
+ * and lookup.
*/
- public Set<ServiceProvider> findServices(String service) {
- readLock.lock();
- try {
- return loaderServices.getOrDefault(service, Collections.emptySet());
- } finally {
- readLock.unlock();
- }
+ static ServicesCatalog create() {
+ return new ServicesCatalog() {
+
+ private Map<String, Set<ServiceProvider>> map = new ConcurrentHashMap<>();
+
+ @Override
+ public void register(Module m) {
+ ModuleDescriptor descriptor = m.getDescriptor();
+
+ for (Provides provides : descriptor.provides().values()) {
+ String service = provides.service();
+ Set<String> providerNames = provides.providers();
+
+ // create a new set to replace the existing
+ Set<ServiceProvider> result = new HashSet<>();
+ Set<ServiceProvider> providers = map.get(service);
+ if (providers != null) {
+ result.addAll(providers);
+ }
+ for (String pn : providerNames) {
+ result.add(new ServiceProvider(m, pn));
+ }
+ map.put(service, Collections.unmodifiableSet(result));
+ }
+
+ }
+
+ @Override
+ public Set<ServiceProvider> findServices(String service) {
+ return map.getOrDefault(service, Collections.emptySet());
+ }
+
+ };
}
-}
+}
\ No newline at end of file
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java Fri May 06 06:23:30 2016 -0700
@@ -40,21 +40,26 @@
*/
public final class SystemModules {
/**
- * Name of the installed modules.
+ * Name of the system modules.
*
- * This array provides a way for InstalledModuleFinder to fallback
+ * This array provides a way for SystemModuleFinder to fallback
* and read module-info.class from the run-time image instead of
* the fastpath.
*/
public static final String[] MODULE_NAMES = new String[1];
/**
+ * Hash of system modules.
+ */
+ public static String[] MODULES_TO_HASH = new String[1];
+
+ /**
* Number of packages in the boot layer from the installed modules.
*
* Don't make it final to avoid inlining during compile time as
* the value will be changed at jlink time.
*/
- public static final int PACKAGES_IN_BOOT_LAYER = 1024;
+ public static int PACKAGES_IN_BOOT_LAYER = 1024;
/**
* Returns a non-empty array of ModuleDescriptors in the run-time image.
@@ -64,4 +69,5 @@
public static ModuleDescriptor[] modules() {
return new ModuleDescriptor[0];
}
-}
\ No newline at end of file
+
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java Fri May 06 06:23:30 2016 -0700
@@ -392,6 +392,7 @@
// matter.
return AccessController.doPrivileged(
new PrivilegedAction<MagicAccessorImpl>() {
+ @SuppressWarnings("deprecation") // Class.newInstance
public MagicAccessorImpl run() {
try {
return (MagicAccessorImpl)
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Fri May 06 06:23:30 2016 -0700
@@ -343,8 +343,8 @@
private static void printStackTraceIfNeeded(Throwable e) {
if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {
- String s = GetPropertyAction
- .getProperty("sun.reflect.debugModuleAccessChecks");
+ String s = GetPropertyAction.privilegedGetProperty(
+ "sun.reflect.debugModuleAccessChecks");
printStackWhenAccessFails =
(s != null && !s.equalsIgnoreCase("false"));
printStackWhenAccessFailsSet = true;
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Fri May 06 06:23:30 2016 -0700
@@ -398,7 +398,7 @@
return;
}
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
String val = props.getProperty("sun.reflect.noInflation");
if (val != null && val.equals("true")) {
noInflation = true;
--- a/jdk/src/java.base/share/classes/module-info.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -166,6 +166,8 @@
java.sql,
java.xml,
jdk.charsets,
+ jdk.jartool,
+ jdk.jlink,
jdk.net,
jdk.scripting.nashorn,
jdk.unsupported,
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Fri May 06 06:23:30 2016 -0700
@@ -84,8 +84,10 @@
import jdk.internal.misc.VM;
-public enum LauncherHelper {
- INSTANCE;
+public final class LauncherHelper {
+
+ // No instantiation
+ private LauncherHelper() {}
// used to identify JavaFX applications
private static final String JAVAFX_APPLICATION_MARKER =
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Fri May 06 06:23:30 2016 -0700
@@ -27,7 +27,7 @@
java.launcher.opt.header = Usage: {0} [options] class [args...]\n\
\ (to execute a class)\n or {0} [options] -jar jarfile [args...]\n\
\ (to execute a jar file)\n\
-\ or {0} [-options] -mp <modulepath> -m <modulename> | <modulename>/<mainclass>\n\
+\ or {0} [options] -mp <modulepath> -m <modulename>[/<mainclass>] [args...]\n\
\ (to execute the main class in a module)\n\
where options include:\n
@@ -51,8 +51,9 @@
\ A {0} separated list of directories, each directory\n\
\ is a directory of modules that replace upgradeable\n\
\ modules in the runtime image\n\
-\ -m <modulename> | <modulename>/<mainclass>\n\
-\ the initial or main module to resolve\n\
+\ -m <modulename>[/<mainclass>]\n\
+\ the initial module to resolve, and the name of the main class\n\
+\ to execute if not specified by the module\n\
\ -addmods <modulename>[,<modulename>...]\n\
\ root modules to resolve in addition to the initial module\n\
\ -limitmods <modulename>[,<modulename>...]\n\
--- a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java Fri May 06 06:23:30 2016 -0700
@@ -53,8 +53,8 @@
private static final AtomicInteger numSockets;
static {
- String prop =
- GetPropertyAction.getProperty("sun.net.maxDatagramSockets");
+ String prop = GetPropertyAction
+ .privilegedGetProperty("sun.net.maxDatagramSockets");
int defmax = DEFAULT_MAX_SOCKETS;
try {
if (prop != null) {
--- a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java Fri May 06 06:23:30 2016 -0700
@@ -67,8 +67,9 @@
return false;
}
try {
- Class<?> c = Class.forName(cm, true, null);
- provider = (FtpClientProvider) c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName(cm, true, null).newInstance();
+ provider = (FtpClientProvider)o;
return true;
} catch (ClassNotFoundException |
IllegalAccessException |
--- a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java Fri May 06 06:23:30 2016 -0700
@@ -40,7 +40,7 @@
*/
public final class SdpSupport {
- private static final String os = GetPropertyAction.getProperty("os.name");
+ private static final String os = GetPropertyAction.privilegedGetProperty("os.name");
private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux")));
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
--- a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java Fri May 06 06:23:30 2016 -0700
@@ -157,7 +157,7 @@
}
try {
String s;
- mailhost = GetPropertyAction.getProperty("mail.host");
+ mailhost = GetPropertyAction.privilegedGetProperty("mail.host");
if (mailhost != null) {
openServer(mailhost);
return;
@@ -183,7 +183,7 @@
setConnectTimeout(to);
try {
String s;
- mailhost = GetPropertyAction.getProperty("mail.host");
+ mailhost = GetPropertyAction.privilegedGetProperty("mail.host");
if (mailhost != null) {
openServer(mailhost);
return;
--- a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Fri May 06 06:23:30 2016 -0700
@@ -183,7 +183,7 @@
}
String execPathList;
- execPathList = GetPropertyAction.getProperty("exec.path");
+ execPathList = GetPropertyAction.privilegedGetProperty("exec.path");
if (execPathList == null) {
// exec.path property not set
return false;
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Fri May 06 06:23:30 2016 -0700
@@ -145,7 +145,7 @@
}
static {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
String keepAlive = props.getProperty("http.keepAlive");
String retryPost = props.getProperty("sun.net.http.retryPost");
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -278,7 +278,7 @@
if (user == null) {
user = "anonymous";
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
String vers = props.getProperty("java.version");
password = props.getProperty("ftp.protocol.user",
"Java" + vers + "@");
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java Fri May 06 06:23:30 2016 -0700
@@ -94,7 +94,7 @@
}
static {
- authPref = GetPropertyAction.getProperty("http.auth.preference");
+ authPref = GetPropertyAction.privilegedGetProperty("http.auth.preference");
// http.auth.preference can be set to SPNEGO or Kerberos.
// In fact they means "Negotiate with SPNEGO" and "Negotiate with
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -207,9 +207,9 @@
};
static {
- Properties props = GetPropertyAction.getProperties();
- maxRedirects = GetIntegerAction.getProperty("http.maxRedirects",
- defaultmaxRedirects);
+ Properties props = GetPropertyAction.privilegedGetProperties();
+ maxRedirects = GetIntegerAction.privilegedGetProperty(
+ "http.maxRedirects", defaultmaxRedirects);
version = props.getProperty("java.version");
String agent = props.getProperty("http.agent");
if (agent == null) {
@@ -225,14 +225,14 @@
enableESBuffer = Boolean.parseBoolean(
props.getProperty("sun.net.http.errorstream.enableBuffering"));
- timeout4ESBuffer = GetIntegerAction
- .getProperty("sun.net.http.errorstream.timeout", 300);
+ timeout4ESBuffer = GetIntegerAction.privilegedGetProperty(
+ "sun.net.http.errorstream.timeout", 300);
if (timeout4ESBuffer <= 0) {
timeout4ESBuffer = 300; // use the default
}
- bufSize4ES = GetIntegerAction
- .getProperty("sun.net.http.errorstream.bufferSize", 4096);
+ bufSize4ES = GetIntegerAction.privilegedGetProperty(
+ "sun.net.http.errorstream.bufferSize", 4096);
if (bufSize4ES <= 0) {
bufSize4ES = 4096; // use the default
}
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Fri May 06 06:23:30 2016 -0700
@@ -139,7 +139,7 @@
//
String ciphers [];
String cipherString =
- GetPropertyAction.getProperty("https.cipherSuites");
+ GetPropertyAction.privilegedGetProperty("https.cipherSuites");
if (cipherString == null || "".equals(cipherString)) {
ciphers = null;
@@ -163,7 +163,7 @@
//
String protocols [];
String protocolString =
- GetPropertyAction.getProperty("https.protocols");
+ GetPropertyAction.privilegedGetProperty("https.protocols");
if (protocolString == null || "".equals(protocolString)) {
protocols = null;
@@ -183,7 +183,8 @@
}
private String getUserAgent() {
- String userAgent = GetPropertyAction.getProperty("https.agent");
+ String userAgent =
+ GetPropertyAction.privilegedGetProperty("https.agent");
if (userAgent == null || userAgent.length() == 0) {
userAgent = "JSSE";
}
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -161,7 +161,7 @@
public Permission getPermission() throws IOException {
Permission p = permission;
if (p == null) {
- String home = GetPropertyAction.getProperty("java.home");
+ String home = GetPropertyAction.privilegedGetProperty("java.home");
p = new FilePermission(home + File.separator + "-", "read");
permission = p;
}
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java Fri May 06 06:23:30 2016 -0700
@@ -56,9 +56,9 @@
URL ru;
boolean localonly = Boolean.parseBoolean(
- GetPropertyAction.getProperty("newdoc.localonly"));
+ GetPropertyAction.privilegedGetProperty("newdoc.localonly"));
- String docurl = GetPropertyAction.getProperty("doc.url");
+ String docurl = GetPropertyAction.privilegedGetProperty("doc.url");
String file = u.getFile();
if (!localonly) {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Fri May 06 06:23:30 2016 -0700
@@ -1019,7 +1019,7 @@
if (!propertyChecked) {
synchronized (FileChannelImpl.class) {
if (!propertyChecked) {
- String value = GetPropertyAction.getProperty(
+ String value = GetPropertyAction.privilegedGetProperty(
"sun.nio.ch.disableSystemWideOverlappingFileLockCheck");
isSharedFileLockTable = ((value == null) || value.equals("false"));
propertyChecked = true;
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Fri May 06 06:23:30 2016 -0700
@@ -374,8 +374,8 @@
}
public static boolean isFastTcpLoopbackRequested() {
- String loopbackProp =
- GetPropertyAction.getProperty("jdk.net.useFastTcpLoopback");
+ String loopbackProp = GetPropertyAction
+ .privilegedGetProperty("jdk.net.useFastTcpLoopback");
boolean enable;
if ("".equals(loopbackProp)) {
enable = true;
@@ -633,8 +633,8 @@
static {
int availLevel = isExclusiveBindAvailable();
if (availLevel >= 0) {
- String exclBindProp =
- GetPropertyAction.getProperty("sun.net.useExclusiveBind");
+ String exclBindProp = GetPropertyAction
+ .privilegedGetProperty("sun.net.useExclusiveBind");
if (exclBindProp != null) {
exclusiveBind = exclBindProp.isEmpty() ?
true : Boolean.parseBoolean(exclBindProp);
--- a/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java Fri May 06 06:23:30 2016 -0700
@@ -165,14 +165,11 @@
GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY));
if (propValue != null) {
try {
- Class<?> c = Class
- .forName(propValue, true, ClassLoader.getSystemClassLoader());
- return ((ThreadFactory)c.newInstance());
- } catch (ClassNotFoundException x) {
- throw new Error(x);
- } catch (InstantiationException x) {
- throw new Error(x);
- } catch (IllegalAccessException x) {
+ @SuppressWarnings("deprecation")
+ Object tmp = Class
+ .forName(propValue, true, ClassLoader.getSystemClassLoader()).newInstance();
+ return (ThreadFactory)tmp;
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException x) {
throw new Error(x);
}
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Fri May 06 06:23:30 2016 -0700
@@ -64,7 +64,8 @@
* for potential future-proofing.
*/
private static long getMaxCachedBufferSize() {
- String s = GetPropertyAction.getProperty("jdk.nio.maxCachedBufferSize");
+ String s = GetPropertyAction
+ .privilegedGetProperty("jdk.nio.maxCachedBufferSize");
if (s != null) {
try {
long m = Long.parseLong(s);
@@ -465,7 +466,8 @@
if (bugLevel == null) {
if (!jdk.internal.misc.VM.isBooted())
return false;
- String value = GetPropertyAction.getProperty("sun.nio.ch.bugLevel");
+ String value = GetPropertyAction
+ .privilegedGetProperty("sun.nio.ch.bugLevel");
bugLevel = (value != null) ? value : "";
}
return bugLevel.equals(bl);
--- a/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java Fri May 06 06:23:30 2016 -0700
@@ -115,10 +115,11 @@
// Instantiate the charset and cache it
try {
- Class<?> c = Class.forName(packagePrefix + "." + cln,
+ @SuppressWarnings("deprecation")
+ Object o= Class.forName(packagePrefix + "." + cln,
true,
- this.getClass().getClassLoader());
- cs = (Charset)c.newInstance();
+ this.getClass().getClassLoader()).newInstance();
+ cs = (Charset)o;
cache.put(csn, cs);
return cs;
} catch (ClassNotFoundException |
--- a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template Fri May 06 06:23:30 2016 -0700
@@ -110,10 +110,11 @@
// Instantiate the charset and cache it
try {
- Class<?> c = Class.forName(packagePrefix + "." + cln,
- true,
- this.getClass().getClassLoader());
- cs = (Charset)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName(packagePrefix + "." + cln,
+ true,
+ this.getClass().getClassLoader()).newInstance();
+ cs = (Charset)o;
cache.put(csn, cs);
return cs;
} catch (ClassNotFoundException |
@@ -164,7 +165,7 @@
return;
initialized = true;
- String map = getProperty("sun.nio.cs.map");
+ String map = GetPropertyAction.privilegedGetProperty("sun.nio.cs.map");
if (map != null) {
String[] maps = map.split(",");
for (int i = 0; i < maps.length; i++) {
@@ -199,9 +200,4 @@
}
}
- private static String getProperty(String key) {
- return GetPropertyAction.getProperty(key);
- }
-
-
}
--- a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java Fri May 06 06:23:30 2016 -0700
@@ -38,7 +38,7 @@
private Util() { }
private static final Charset jnuEncoding = Charset.forName(
- GetPropertyAction.getProperty("sun.jnu.encoding"));
+ GetPropertyAction.privilegedGetProperty("sun.jnu.encoding"));
/**
* Returns {@code Charset} corresponding to the sun.jnu.encoding property
--- a/jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.action;
-
-import java.security.Security;
-
-/**
- * A convenience class for retrieving the boolean value of a security property
- * as a privileged action.
- *
- * <p>An instance of this class can be used as the argument of
- * <code>AccessController.doPrivileged</code>.
- *
- * <p>The following code retrieves the boolean value of the security
- * property named <code>"prop"</code> as a privileged action:
- *
- * <pre>
- * boolean b = java.security.AccessController.doPrivileged
- * (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
- * </pre>
- *
- */
-public class GetBooleanSecurityPropertyAction
- implements java.security.PrivilegedAction<Boolean> {
- private String theProp;
-
- /**
- * Constructor that takes the name of the security property whose boolean
- * value needs to be determined.
- *
- * @param theProp the name of the security property
- */
- public GetBooleanSecurityPropertyAction(String theProp) {
- this.theProp = theProp;
- }
-
- /**
- * Determines the boolean value of the security property whose name was
- * specified in the constructor.
- *
- * @return the <code>Boolean</code> value of the security property.
- */
- public Boolean run() {
- boolean b = false;
- try {
- String value = Security.getProperty(theProp);
- b = (value != null) && value.equalsIgnoreCase("true");
- } catch (NullPointerException e) {}
- return b;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java Fri May 06 06:23:30 2016 -0700
@@ -118,9 +118,14 @@
* if no security manager is present. This is unsafe for inclusion in a
* public API but allowable here since this class is now encapsulated.
*
+ * Note that this method performs a privileged action using caller-provided
+ * inputs. The caller of this method should take care to ensure that the
+ * inputs are not tainted and the returned property is not made accessible
+ * to untrusted code if it contains sensitive information.
+ *
* @param theProp the name of the system property.
*/
- public static Integer getProperty(String theProp) {
+ public static Integer privilegedGetProperty(String theProp) {
if (System.getSecurityManager() == null) {
return Integer.getInteger(theProp);
} else {
@@ -134,10 +139,16 @@
* if no security manager is present. This is unsafe for inclusion in a
* public API but allowable here since this class is now encapsulated.
*
+ * Note that this method performs a privileged action using caller-provided
+ * inputs. The caller of this method should take care to ensure that the
+ * inputs are not tainted and the returned property is not made accessible
+ * to untrusted code if it contains sensitive information.
+ *
* @param theProp the name of the system property.
* @param defaultVal the default value.
*/
- public static Integer getProperty(String theProp, int defaultVal) {
+ public static Integer privilegedGetProperty(String theProp,
+ int defaultVal) {
Integer value;
if (System.getSecurityManager() == null) {
value = Integer.getInteger(theProp);
--- a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java Fri May 06 06:23:30 2016 -0700
@@ -93,9 +93,14 @@
* if no security manager is present. This is unsafe for inclusion in a
* public API but allowable here since this class is now encapsulated.
*
+ * Note that this method performs a privileged action using caller-provided
+ * inputs. The caller of this method should take care to ensure that the
+ * inputs are not tainted and the returned property is not made accessible
+ * to untrusted code if it contains sensitive information.
+ *
* @param theProp the name of the system property.
*/
- public static String getProperty(String theProp) {
+ public static String privilegedGetProperty(String theProp) {
if (System.getSecurityManager() == null) {
return System.getProperty(theProp);
} else {
@@ -109,10 +114,16 @@
* if no security manager is present. This is unsafe for inclusion in a
* public API but allowable here since this class is now encapsulated.
*
+ * Note that this method performs a privileged action using caller-provided
+ * inputs. The caller of this method should take care to ensure that the
+ * inputs are not tainted and the returned property is not made accessible
+ * to untrusted code if it contains sensitive information.
+ *
* @param theProp the name of the system property.
* @param defaultVal the default value.
*/
- public static String getProperty(String theProp, String defaultVal) {
+ public static String privilegedGetProperty(String theProp,
+ String defaultVal) {
if (System.getSecurityManager() == null) {
return System.getProperty(theProp, defaultVal);
} else {
@@ -126,8 +137,13 @@
* having to go through doPrivileged if no security manager is present.
* This is unsafe for inclusion in a public API but allowable here since
* this class is now encapsulated.
+ *
+ * Note that this method performs a privileged action, and callers of
+ * this method should take care to ensure that the returned properties
+ * are not made accessible to untrusted code since it may contain
+ * sensitive information.
*/
- public static Properties getProperties() {
+ public static Properties privilegedGetProperties() {
if (System.getSecurityManager() == null) {
return System.getProperties();
} else {
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Fri May 06 06:23:30 2016 -0700
@@ -185,7 +185,9 @@
try {
Class<?> c = Class.forName("apple.security.AppleProvider");
if (Provider.class.isAssignableFrom(c)) {
- return (Provider) c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ return (Provider) tmp;
} else {
return null;
}
@@ -386,6 +388,7 @@
Provider p = AccessController.doPrivileged
(new PrivilegedExceptionAction<Provider>() {
+ @SuppressWarnings("deprecation") // Class.newInstance
public Provider run() throws Exception {
return (Provider) provClass.newInstance();
}
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Fri May 06 06:23:30 2016 -0700
@@ -218,11 +218,10 @@
}
}
- Object inst = null;
+ @SuppressWarnings("deprecation")
+ Object inst = (keyClass != null) ? keyClass.newInstance() : null;
PKCS8Key result;
- if (keyClass != null)
- inst = keyClass.newInstance();
if (inst instanceof PKCS8Key) {
result = (PKCS8Key) inst;
result.algid = algid;
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Fri May 06 06:23:30 2016 -0700
@@ -70,7 +70,7 @@
* By default this is false.
* This incompatibility was introduced by 4532506.
*/
- String prop = GetPropertyAction.getProperty(SERIAL_PROP);
+ String prop = GetPropertyAction.privilegedGetProperty(SERIAL_PROP);
SERIAL_INTEROP = "true".equalsIgnoreCase(prop);
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,10 @@
import java.util.Collections;
import java.util.Set;
import java.util.EnumSet;
-import java.util.HashSet;
import java.math.BigInteger;
import java.security.PublicKey;
import java.security.KeyFactory;
import java.security.AlgorithmParameters;
-import java.security.NoSuchAlgorithmException;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.X509CRL;
@@ -48,10 +46,13 @@
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXReason;
-import java.io.IOException;
-import java.security.interfaces.*;
-import java.security.spec.*;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import sun.security.util.AnchorCertificates;
+import sun.security.util.CertConstraintParameters;
+import sun.security.util.Debug;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl;
@@ -69,6 +70,7 @@
* @see PKIXParameters
*/
public final class AlgorithmChecker extends PKIXCertPathChecker {
+ private static final Debug debug = Debug.getInstance("certpath");
private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey;
@@ -88,6 +90,14 @@
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
+ // If there is no "cacerts" keyword, then disable anchor checking
+ private static final boolean publicCALimits =
+ certPathDefaultConstraints.checkProperty("jdkCA");
+
+ // If anchor checking enabled, this will be true if the trust anchor
+ // has a match in the cacerts file
+ private boolean trustedMatch = false;
+
/**
* Create a new <code>AlgorithmChecker</code> with the algorithm
* constraints specified in security property
@@ -136,6 +146,11 @@
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+ // Check for anchor certificate restrictions
+ trustedMatch = checkFingerprint(anchor.getTrustedCert());
+ if (trustedMatch && debug != null) {
+ debug.println("trustedMatch = true");
+ }
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
@@ -144,6 +159,19 @@
this.constraints = constraints;
}
+ // Check this 'cert' for restrictions in the AnchorCertificates
+ // trusted certificates list
+ private static boolean checkFingerprint(X509Certificate cert) {
+ if (!publicCALimits) {
+ return false;
+ }
+
+ if (debug != null) {
+ debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
+ }
+ return AnchorCertificates.contains(cert);
+ }
+
@Override
public void init(boolean forward) throws CertPathValidatorException {
// Note that this class does not support forward mode.
@@ -181,36 +209,8 @@
return;
}
- X509CertImpl x509Cert = null;
- try {
- x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
- } catch (CertificateException ce) {
- throw new CertPathValidatorException(ce);
- }
-
- PublicKey currPubKey = x509Cert.getPublicKey();
- String currSigAlg = x509Cert.getSigAlgName();
-
- AlgorithmId algorithmId = null;
- try {
- algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
- } catch (CertificateException ce) {
- throw new CertPathValidatorException(ce);
- }
-
- AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
-
- // Check the current signature algorithm
- if (!constraints.permits(
- SIGNATURE_PRIMITIVE_SET,
- currSigAlg, currSigAlgParams)) {
- throw new CertPathValidatorException(
- "Algorithm constraints check failed: " + currSigAlg,
- null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
- }
-
// check the key usage and key size
- boolean[] keyUsage = x509Cert.getKeyUsage();
+ boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
if (keyUsage != null && keyUsage.length < 9) {
throw new CertPathValidatorException(
"incorrect KeyUsage extension",
@@ -248,27 +248,67 @@
if (primitives.isEmpty()) {
throw new CertPathValidatorException(
- "incorrect KeyUsage extension",
+ "incorrect KeyUsage extension bits",
null, null, -1, PKIXReason.INVALID_KEY_USAGE);
}
}
- if (!constraints.permits(primitives, currPubKey)) {
- throw new CertPathValidatorException(
- "algorithm constraints check failed",
- null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ PublicKey currPubKey = cert.getPublicKey();
+
+ // Check against DisabledAlgorithmConstraints certpath constraints.
+ // permits() will throw exception on failure.
+ certPathDefaultConstraints.permits(primitives,
+ new CertConstraintParameters((X509Certificate)cert,
+ trustedMatch));
+ // new CertConstraintParameters(x509Cert, trustedMatch));
+ // If there is no previous key, set one and exit
+ if (prevPubKey == null) {
+ prevPubKey = currPubKey;
+ return;
+ }
+
+ X509CertImpl x509Cert;
+ AlgorithmId algorithmId;
+ try {
+ x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+ algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+ } catch (CertificateException ce) {
+ throw new CertPathValidatorException(ce);
+ }
+
+ AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+ String currSigAlg = x509Cert.getSigAlgName();
+
+ // If 'constraints' is not of DisabledAlgorithmConstraints, check all
+ // everything individually
+ if (!(constraints instanceof DisabledAlgorithmConstraints)) {
+ // Check the current signature algorithm
+ if (!constraints.permits(
+ SIGNATURE_PRIMITIVE_SET,
+ currSigAlg, currSigAlgParams)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on signature " +
+ "algorithm: " + currSigAlg, null, null, -1,
+ BasicReason.ALGORITHM_CONSTRAINED);
+ }
+
+ if (!constraints.permits(primitives, currPubKey)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on keysize: " +
+ sun.security.util.KeyUtil.getKeySize(currPubKey),
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
}
// Check with previous cert for signature algorithm and public key
if (prevPubKey != null) {
- if (currSigAlg != null) {
- if (!constraints.permits(
- SIGNATURE_PRIMITIVE_SET,
- currSigAlg, prevPubKey, currSigAlgParams)) {
- throw new CertPathValidatorException(
- "Algorithm constraints check failed: " + currSigAlg,
- null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
- }
+ if (!constraints.permits(
+ SIGNATURE_PRIMITIVE_SET,
+ currSigAlg, prevPubKey, currSigAlgParams)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on " +
+ "signature algorithm: " + currSigAlg,
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
// Inherit key parameters from previous key
@@ -282,7 +322,7 @@
DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
if (params == null) {
throw new CertPathValidatorException(
- "Key parameters missing");
+ "Key parameters missing from public key.");
}
try {
@@ -330,6 +370,11 @@
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
+ // Check for anchor certificate restrictions
+ trustedMatch = checkFingerprint(anchor.getTrustedCert());
+ if (trustedMatch && debug != null) {
+ debug.println("trustedMatch = true");
+ }
} else {
prevPubKey = anchor.getCAPublicKey();
}
@@ -370,7 +415,8 @@
if (!certPathDefaultConstraints.permits(
SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
throw new CertPathValidatorException(
- "algorithm check failed: " + sigAlgName + " is disabled",
+ "Algorithm constraints check failed on signature algorithm: " +
+ sigAlgName + " is disabled",
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Fri May 06 06:23:30 2016 -0700
@@ -131,8 +131,8 @@
} catch (CertPathValidatorException cpve) {
throw new CertPathValidatorException(cpve.getMessage(),
- cpve.getCause(), cpOriginal, cpSize - (i + 1),
- cpve.getReason());
+ (cpve.getCause() != null) ? cpve.getCause() : cpve,
+ cpOriginal, cpSize - (i + 1), cpve.getReason());
}
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java Fri May 06 06:23:30 2016 -0700
@@ -43,7 +43,6 @@
import static sun.security.provider.certpath.OCSP.*;
import static sun.security.provider.certpath.PKIX.*;
-import sun.security.action.GetPropertyAction;
import sun.security.x509.*;
import static sun.security.x509.PKIXExtensions.*;
import sun.security.util.Debug;
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java Fri May 06 06:23:30 2016 -0700
@@ -84,7 +84,7 @@
public static final int MAX_RESTRICTED_EXPLEN = 64;
private static final boolean restrictExpLen =
- "true".equalsIgnoreCase(GetPropertyAction.getProperty(
+ "true".equalsIgnoreCase(GetPropertyAction.privilegedGetProperty(
"sun.security.rsa.restrictRSAExponent", "true"));
// instance used for static translateKey();
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java Fri May 06 06:23:30 2016 -0700
@@ -50,7 +50,7 @@
providers = new HashMap<>();
static {
- String path = GetPropertyAction.getProperty("java.home");
+ String path = GetPropertyAction.privilegedGetProperty("java.home");
ServiceLoader<ClientKeyExchangeService> sc =
AccessController.doPrivileged(
(PrivilegedAction<ServiceLoader<ClientKeyExchangeService>>)
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Fri May 06 06:23:30 2016 -0700
@@ -45,7 +45,7 @@
private static String args;
static {
- args = GetPropertyAction.getProperty("javax.net.debug", "");
+ args = GetPropertyAction.privilegedGetProperty("javax.net.debug", "");
args = args.toLowerCase(Locale.ENGLISH);
if (args.equals("help")) {
Help();
@@ -178,11 +178,11 @@
/**
* Return the value of the boolean System property propName.
*
- * Note use of doPrivileged(). Do make accessible to applications.
+ * Note use of privileged action. Do NOT make accessible to applications.
*/
static boolean getBooleanProperty(String propName, boolean defaultValue) {
// if set, require value of either true or false
- String b = GetPropertyAction.getProperty(propName);
+ String b = GetPropertyAction.privilegedGetProperty(propName);
if (b == null) {
return defaultValue;
} else if (b.equalsIgnoreCase("false")) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Fri May 06 06:23:30 2016 -0700
@@ -656,7 +656,8 @@
// the provider service. Instead, please handle the initialization
// exception in the caller's constructor.
static {
- String property = GetPropertyAction.getProperty(PROPERTY_NAME);
+ String property = GetPropertyAction
+ .privilegedGetProperty(PROPERTY_NAME);
if (property != null && property.length() != 0) {
// remove double quote marks from beginning/end of the property
if (property.length() > 1 && property.charAt(0) == '"' &&
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Fri May 06 06:23:30 2016 -0700
@@ -119,8 +119,8 @@
private long statusRespTimeout;
static {
- String property =
- GetPropertyAction.getProperty("jdk.tls.ephemeralDHKeySize");
+ String property = GetPropertyAction
+ .privilegedGetProperty("jdk.tls.ephemeralDHKeySize");
if (property == null || property.length() == 0) {
useLegacyEphemeralDHKeys = false;
useSmartEphemeralDHKeys = false;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java Fri May 06 06:23:30 2016 -0700
@@ -73,8 +73,8 @@
DEFAULT_CACHE_LIFETIME));
cacheLifetime = life > 0 ? life : 0;
- String uriStr =
- GetPropertyAction.getProperty("jdk.tls.stapling.responderURI");
+ String uriStr = GetPropertyAction
+ .privilegedGetProperty("jdk.tls.stapling.responderURI");
URI tmpURI;
try {
tmpURI = ((uriStr != null && !uriStr.isEmpty()) ?
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri May 06 06:23:30 2016 -0700
@@ -728,6 +728,7 @@
provClass = Class.forName(provName);
}
+ @SuppressWarnings("deprecation")
Object obj = provClass.newInstance();
if (!(obj instanceof Provider)) {
MessageFormat form = new MessageFormat
--- a/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java Fri May 06 06:23:30 2016 -0700
@@ -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,7 +29,6 @@
import java.security.AlgorithmConstraints;
import java.security.PrivilegedAction;
import java.security.Security;
-import java.util.Map;
import java.util.Set;
/**
@@ -45,8 +44,7 @@
}
// Get algorithm constraints from the specified security property.
- private static void loadAlgorithmsMap(Map<String, String[]> algorithmsMap,
- String propertyName) {
+ static String[] getAlgorithms(String propertyName) {
String property = AccessController.doPrivileged(
(PrivilegedAction<String>) () -> Security.getProperty(
propertyName));
@@ -68,18 +66,7 @@
if (algorithmsInProperty == null) {
algorithmsInProperty = new String[0];
}
- algorithmsMap.put(propertyName, algorithmsInProperty);
- }
-
- static String[] getAlgorithms(Map<String, String[]> algorithmsMap,
- String propertyName) {
- synchronized (algorithmsMap) {
- if (!algorithmsMap.containsKey(propertyName)) {
- loadAlgorithmsMap(algorithmsMap, propertyName);
- }
-
- return algorithmsMap.get(propertyName);
- }
+ return algorithmsInProperty;
}
static boolean checkAlgorithm(String[] algorithms, String algorithm,
--- a/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -40,19 +40,7 @@
private static final Pattern pattern =
Pattern.compile("with|and|(?<!padd)in", Pattern.CASE_INSENSITIVE);
- /**
- * Decompose the standard algorithm name into sub-elements.
- * <p>
- * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
- * so that we can check the "SHA1" and "RSA" algorithm constraints
- * separately.
- * <p>
- * Please override the method if need to support more name pattern.
- */
- public Set<String> decompose(String algorithm) {
- if (algorithm == null || algorithm.length() == 0) {
- return new HashSet<>();
- }
+ private static Set<String> decomposeImpl(String algorithm) {
// algorithm/mode/padding
String[] transTockens = transPattern.split(algorithm);
@@ -79,6 +67,24 @@
elements.add(token);
}
}
+ return elements;
+ }
+
+ /**
+ * Decompose the standard algorithm name into sub-elements.
+ * <p>
+ * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+ * so that we can check the "SHA1" and "RSA" algorithm constraints
+ * separately.
+ * <p>
+ * Please override the method if need to support more name pattern.
+ */
+ public Set<String> decompose(String algorithm) {
+ if (algorithm == null || algorithm.length() == 0) {
+ return new HashSet<>();
+ }
+
+ Set<String> elements = decomposeImpl(algorithm);
// In Java standard algorithm name specification, for different
// purpose, the SHA-1 and SHA-2 algorithm names are different. For
@@ -130,4 +136,40 @@
return elements;
}
+ private static void hasLoop(Set<String> elements, String find, String replace) {
+ if (elements.contains(find)) {
+ if (!elements.contains(replace)) {
+ elements.add(replace);
+ }
+ elements.remove(find);
+ }
+ }
+
+ /*
+ * This decomposes a standard name into sub-elements with a consistent
+ * message digest algorithm name to avoid overly complicated checking.
+ */
+ public static Set<String> decomposeOneHash(String algorithm) {
+ if (algorithm == null || algorithm.length() == 0) {
+ return new HashSet<>();
+ }
+
+ Set<String> elements = decomposeImpl(algorithm);
+
+ hasLoop(elements, "SHA-1", "SHA1");
+ hasLoop(elements, "SHA-224", "SHA224");
+ hasLoop(elements, "SHA-256", "SHA256");
+ hasLoop(elements, "SHA-384", "SHA384");
+ hasLoop(elements, "SHA-512", "SHA512");
+
+ return elements;
+ }
+
+ /*
+ * The provided message digest algorithm name will return a consistent
+ * naming scheme.
+ */
+ public static String hashName(String algorithm) {
+ return algorithm.replace("-", "");
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.AccessController;
+import java.security.KeyStore;
+import java.security.PrivilegedAction;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashSet;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * The purpose of this class is to determine the trust anchor certificates is in
+ * the cacerts file. This is used for PKIX CertPath checking.
+ */
+public class AnchorCertificates {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+ private static final String HASH = "SHA-256";
+ private static HashSet<String> certs;
+
+ static {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ File f = new File(System.getProperty("java.home"),
+ "lib/security/cacerts");
+ KeyStore cacerts;
+ try {
+ cacerts = KeyStore.getInstance("JKS");
+ try (FileInputStream fis = new FileInputStream(f)) {
+ cacerts.load(fis, "changeit".toCharArray());
+ certs = new HashSet<>();
+ Enumeration<String> list = cacerts.aliases();
+ String alias;
+ while (list.hasMoreElements()) {
+ alias = list.nextElement();
+ // Check if this cert is labeled a trust anchor.
+ if (alias.contains(" [jdk")) {
+ X509Certificate cert = (X509Certificate) cacerts
+ .getCertificate(alias);
+ certs.add(X509CertImpl.getFingerprint(HASH, cert));
+ }
+ }
+ }
+ } catch (Exception e) {
+ if (debug != null) {
+ debug.println("Error parsing cacerts");
+ }
+ e.printStackTrace();
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Checks if a certificate is a trust anchor.
+ *
+ * @param cert the certificate to check
+ * @return true if the certificate is trusted.
+ */
+ public static boolean contains(X509Certificate cert) {
+ String key = X509CertImpl.getFingerprint(HASH, cert);
+ boolean result = certs.contains(key);
+ if (result && debug != null) {
+ debug.println("AnchorCertificate.contains: matched " +
+ cert.getSubjectDN());
+ }
+ return result;
+ }
+
+ private AnchorCertificates() {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This class is a wrapper for keeping state and passing objects between PKIX,
+ * AlgorithmChecker, and DisabledAlgorithmConstraints.
+ */
+public class CertConstraintParameters {
+ // A certificate being passed to check against constraints.
+ private final X509Certificate cert;
+
+ // This is true if the trust anchor in the certificate chain matches a cert
+ // in AnchorCertificates
+ private final boolean trustedMatch;
+
+ public CertConstraintParameters(X509Certificate c, boolean match) {
+ cert = c;
+ trustedMatch = match;
+ }
+
+ public CertConstraintParameters(X509Certificate c) {
+ this(c, false);
+ }
+
+ // Returns if the trust anchor has a match if anchor checking is enabled.
+ public boolean isTrustedMatch() {
+ return trustedMatch;
+ }
+
+ public X509Certificate getCertificate() {
+ return cert;
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/security/util/Debug.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/Debug.java Fri May 06 06:23:30 2016 -0700
@@ -43,10 +43,10 @@
private static String args;
static {
- args = GetPropertyAction.getProperty("java.security.debug");
+ args = GetPropertyAction.privilegedGetProperty("java.security.debug");
- String args2 =
- GetPropertyAction.getProperty("java.security.auth.debug");
+ String args2 = GetPropertyAction
+ .privilegedGetProperty("java.security.auth.debug");
if (args == null) {
args = args2;
--- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,14 @@
import java.security.CryptoPrimitive;
import java.security.AlgorithmParameters;
import java.security.Key;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertPathValidatorException.BasicReason;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Locale;
+import java.util.Map;
import java.util.Set;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -44,6 +46,7 @@
* for the syntax of the disabled algorithm string.
*/
public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
+ private static final Debug debug = Debug.getInstance("certpath");
// the known security property, jdk.certpath.disabledAlgorithms
public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
@@ -53,13 +56,8 @@
public static final String PROPERTY_TLS_DISABLED_ALGS =
"jdk.tls.disabledAlgorithms";
- private static final Map<String, String[]> disabledAlgorithmsMap =
- new HashMap<>();
- private static final Map<String, KeySizeConstraints> keySizeConstraintsMap =
- new HashMap<>();
-
private final String[] disabledAlgorithms;
- private final KeySizeConstraints keySizeConstraints;
+ private final Constraints algorithmConstraints;
/**
* Initialize algorithm constraints with the specified security property.
@@ -74,11 +72,14 @@
public DisabledAlgorithmConstraints(String propertyName,
AlgorithmDecomposer decomposer) {
super(decomposer);
- disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName);
- keySizeConstraints = getKeySizeConstraints(disabledAlgorithms,
- propertyName);
+ disabledAlgorithms = getAlgorithms(propertyName);
+ algorithmConstraints = new Constraints(disabledAlgorithms);
}
+ /*
+ * This only checks if the algorithm has been completely disabled. If
+ * there are keysize or other limit, this method allow the algorithm.
+ */
@Override
public final boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) {
@@ -91,11 +92,19 @@
return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
}
+ /*
+ * Checks if the key algorithm has been disabled or constraints have been
+ * placed on the key.
+ */
@Override
public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
return checkConstraints(primitives, "", key, null);
}
+ /*
+ * Checks if the key algorithm has been disabled or if constraints have
+ * been placed on the key.
+ */
@Override
public final boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) {
@@ -107,7 +116,39 @@
return checkConstraints(primitives, algorithm, key, parameters);
}
- // Check algorithm constraints
+ /*
+ * Check if a x509Certificate object is permitted. Check if all
+ * algorithms are allowed, certificate constraints, and the
+ * public key against key constraints.
+ *
+ * Uses new style permit() which throws exceptions.
+ */
+ public final void permits(Set<CryptoPrimitive> primitives,
+ CertConstraintParameters cp) throws CertPathValidatorException {
+ checkConstraints(primitives, cp);
+ }
+
+ /*
+ * Check if Certificate object is within the constraints.
+ * Uses new style permit() which throws exceptions.
+ */
+ public final void permits(Set<CryptoPrimitive> primitives,
+ X509Certificate cert) throws CertPathValidatorException {
+ checkConstraints(primitives, new CertConstraintParameters(cert));
+ }
+
+ // Check if a string is contained inside the property
+ public boolean checkProperty(String param) {
+ param = param.toLowerCase(Locale.ENGLISH);
+ for (String block : disabledAlgorithms) {
+ if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Check algorithm constraints with key and algorithm
private boolean checkConstraints(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) {
@@ -116,7 +157,7 @@
throw new IllegalArgumentException("The key cannot be null");
}
- // check the target algorithm
+ // check the signature algorithm
if (algorithm != null && algorithm.length() != 0) {
if (!permits(primitives, algorithm, parameters)) {
return false;
@@ -129,97 +170,203 @@
}
// check the key constraints
- if (keySizeConstraints.disables(key)) {
- return false;
- }
-
- return true;
+ return algorithmConstraints.permits(key);
}
- private static KeySizeConstraints getKeySizeConstraints(
- String[] disabledAlgorithms, String propertyName) {
- synchronized (keySizeConstraintsMap) {
- if(!keySizeConstraintsMap.containsKey(propertyName)) {
- // map the key constraints
- KeySizeConstraints keySizeConstraints =
- new KeySizeConstraints(disabledAlgorithms);
- keySizeConstraintsMap.put(propertyName, keySizeConstraints);
- }
+ /*
+ * Check algorithm constraints with Certificate
+ * Uses new style permit() which throws exceptions.
+ */
+ private void checkConstraints(Set<CryptoPrimitive> primitives,
+ CertConstraintParameters cp) throws CertPathValidatorException {
+
+ X509Certificate cert = cp.getCertificate();
+ String algorithm = cert.getSigAlgName();
- return keySizeConstraintsMap.get(propertyName);
+ // Check signature algorithm is not disabled
+ if (!permits(primitives, algorithm, null)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on disabled "+
+ "signature algorithm: " + algorithm,
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
+
+ // Check key algorithm is not disabled
+ if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on disabled "+
+ "public key algorithm: " + algorithm,
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
+
+ // Check the certificate and key constraints
+ algorithmConstraints.permits(cp);
+
}
/**
- * key constraints
+ * Key and Certificate Constraints
+ *
+ * The complete disabling of an algorithm is not handled by Constraints or
+ * Constraint classes. That is addressed with
+ * permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
+ *
+ * When passing a Key to permit(), the boolean return values follow the
+ * same as the interface class AlgorithmConstraints.permit(). This is to
+ * maintain compatibility:
+ * 'true' means the operation is allowed.
+ * 'false' means it failed the constraints and is disallowed.
+ *
+ * When passing CertConstraintParameters through permit(), an exception
+ * will be thrown on a failure to better identify why the operation was
+ * disallowed.
*/
- private static class KeySizeConstraints {
- private static final Pattern pattern = Pattern.compile(
- "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
- private Map<String, Set<KeySizeConstraint>> constraintsMap =
- Collections.synchronizedMap(
- new HashMap<String, Set<KeySizeConstraint>>());
+ private static class Constraints {
+ private Map<String, Set<Constraint>> constraintsMap = new HashMap<>();
+ private static final Pattern keySizePattern = Pattern.compile(
+ "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
- public KeySizeConstraints(String[] restrictions) {
- for (String restriction : restrictions) {
- if (restriction == null || restriction.isEmpty()) {
+ public Constraints(String[] constraintArray) {
+ for (String constraintEntry : constraintArray) {
+ if (constraintEntry == null || constraintEntry.isEmpty()) {
continue;
}
- Matcher matcher = pattern.matcher(restriction);
- if (matcher.matches()) {
- String algorithm = matcher.group(1);
+ constraintEntry = constraintEntry.trim();
+ if (debug != null) {
+ debug.println("Constraints: " + constraintEntry);
+ }
- KeySizeConstraint.Operator operator =
- KeySizeConstraint.Operator.of(matcher.group(2));
- int length = Integer.parseInt(matcher.group(3));
+ // Check if constraint is a complete disabling of an
+ // algorithm or has conditions.
+ String algorithm;
+ String policy;
+ int space = constraintEntry.indexOf(' ');
+ if (space > 0) {
+ algorithm = AlgorithmDecomposer.hashName(
+ constraintEntry.substring(0, space).
+ toUpperCase(Locale.ENGLISH));
+ policy = constraintEntry.substring(space + 1);
+ } else {
+ constraintsMap.computeIfAbsent(
+ constraintEntry.toUpperCase(Locale.ENGLISH),
+ k -> new HashSet<>());
+ continue;
+ }
- algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+ // Convert constraint conditions into Constraint classes
+ Constraint c, lastConstraint = null;
+ // Allow only one jdkCA entry per constraint entry
+ boolean jdkCALimit = false;
+
+ for (String entry : policy.split("&")) {
+ entry = entry.trim();
- synchronized (constraintsMap) {
- if (!constraintsMap.containsKey(algorithm)) {
- constraintsMap.put(algorithm,
- new HashSet<KeySizeConstraint>());
+ Matcher matcher = keySizePattern.matcher(entry);
+ if (matcher.matches()) {
+ if (debug != null) {
+ debug.println("Constraints set to keySize: " +
+ entry);
}
+ c = new KeySizeConstraint(algorithm,
+ KeySizeConstraint.Operator.of(matcher.group(1)),
+ Integer.parseInt(matcher.group(2)));
- Set<KeySizeConstraint> constraintSet =
- constraintsMap.get(algorithm);
- KeySizeConstraint constraint =
- new KeySizeConstraint(operator, length);
- constraintSet.add(constraint);
+ } else if (entry.equalsIgnoreCase("jdkCA")) {
+ if (debug != null) {
+ debug.println("Constraints set to jdkCA.");
+ }
+ if (jdkCALimit) {
+ throw new IllegalArgumentException("Only one " +
+ "jdkCA entry allowed in property. " +
+ "Constraint: " + constraintEntry);
+ }
+ c = new jdkCAConstraint(algorithm);
+ jdkCALimit = true;
+ } else {
+ throw new IllegalArgumentException("Error in security" +
+ " property. Constraint unknown: " + entry);
}
+
+ // Link multiple conditions for a single constraint
+ // into a linked list.
+ if (lastConstraint == null) {
+ if (!constraintsMap.containsKey(algorithm)) {
+ constraintsMap.putIfAbsent(algorithm,
+ new HashSet<>());
+ }
+ constraintsMap.get(algorithm).add(c);
+ } else {
+ lastConstraint.nextConstraint = c;
+ }
+ lastConstraint = c;
}
}
}
- // Does this KeySizeConstraints disable the specified key?
- public boolean disables(Key key) {
- String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
- synchronized (constraintsMap) {
- if (constraintsMap.containsKey(algorithm)) {
- Set<KeySizeConstraint> constraintSet =
- constraintsMap.get(algorithm);
- for (KeySizeConstraint constraint : constraintSet) {
- if (constraint.disables(key)) {
- return true;
- }
+ // Get applicable constraints based off the signature algorithm
+ private Set<Constraint> getConstraints(String algorithm) {
+ return constraintsMap.get(algorithm);
+ }
+
+ // Check if KeySizeConstraints permit the specified key
+ public boolean permits(Key key) {
+ Set<Constraint> set = getConstraints(key.getAlgorithm());
+ if (set == null) {
+ return true;
+ }
+ for (Constraint constraint : set) {
+ if (!constraint.permits(key)) {
+ if (debug != null) {
+ debug.println("keySizeConstraint: failed key " +
+ "constraint check " + KeyUtil.getKeySize(key));
}
+ return false;
}
}
+ return true;
+ }
- return false;
+ // Check if constraints permit this cert.
+ public void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException {
+ X509Certificate cert = cp.getCertificate();
+
+ if (debug != null) {
+ debug.println("Constraints.permits(): " + cert.getSigAlgName());
+ }
+
+ // Get all signature algorithms to check for constraints
+ Set<String> algorithms =
+ AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName());
+ if (algorithms == null || algorithms.isEmpty()) {
+ return;
+ }
+
+ // Attempt to add the public key algorithm to the set
+ algorithms.add(cert.getPublicKey().getAlgorithm());
+
+ // Check all applicable constraints
+ for (String algorithm : algorithms) {
+ Set<Constraint> set = getConstraints(algorithm);
+ if (set == null) {
+ continue;
+ }
+ for (Constraint constraint : set) {
+ constraint.permits(cp);
+ }
+ }
}
}
- /**
- * Key size constraint.
- *
- * e.g. "keysize <= 1024"
- */
- private static class KeySizeConstraint {
+ // Abstract class for algorithm constraint checking
+ private abstract static class Constraint {
+ String algorithm;
+ Constraint nextConstraint = null;
+
// operator
- static enum Operator {
+ enum Operator {
EQ, // "=="
NE, // "!="
LT, // "<"
@@ -243,16 +390,77 @@
return GE;
}
- throw new IllegalArgumentException(
- s + " is not a legal Operator");
+ throw new IllegalArgumentException("Error in security " +
+ "property. " + s + " is not a legal Operator");
}
}
+ /**
+ * Check if an algorithm constraint permit this key to be used.
+ * @param key Public key
+ * @return true if constraints do not match
+ */
+ public boolean permits(Key key) {
+ return true;
+ }
+
+ /**
+ * Check if an algorithm constraint is permit this certificate to
+ * be used.
+ * @param cp CertificateParameter containing certificate and state info
+ * @return true if constraints do not match
+ */
+ public abstract void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException;
+ }
+
+ /*
+ * This class contains constraints dealing with the certificate chain
+ * of the certificate.
+ */
+ private static class jdkCAConstraint extends Constraint {
+ jdkCAConstraint(String algo) {
+ algorithm = algo;
+ }
+
+ /*
+ * Check if each constraint fails and check if there is a linked
+ * constraint Any permitted constraint will exit the linked list
+ * to allow the operation.
+ */
+ public void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException {
+ if (debug != null) {
+ debug.println("jdkCAConstraints.permits(): " + algorithm);
+ }
+
+ // Return false if the chain has a trust anchor in cacerts
+ if (cp.isTrustedMatch()) {
+ if (nextConstraint != null) {
+ nextConstraint.permits(cp);
+ return;
+ }
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on certificate " +
+ "anchor limits",
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
+ }
+ }
+
+
+ /*
+ * This class contains constraints dealing with the key size
+ * support limits per algorithm. e.g. "keySize <= 1024"
+ */
+ private static class KeySizeConstraint extends Constraint {
+
private int minSize; // the minimal available key size
private int maxSize; // the maximal available key size
private int prohibitedSize = -1; // unavailable key sizes
- public KeySizeConstraint(Operator operator, int length) {
+ public KeySizeConstraint(String algo, Operator operator, int length) {
+ algorithm = algo;
switch (operator) {
case EQ: // an unavailable key size
this.minSize = 0;
@@ -286,21 +494,59 @@
}
}
- // Does this key constraint disable the specified key?
- public boolean disables(Key key) {
- int size = KeyUtil.getKeySize(key);
+ /*
+ * If we are passed a certificate, extract the public key and use it.
+ *
+ * Check if each constraint fails and check if there is a linked
+ * constraint Any permitted constraint will exit the linked list
+ * to allow the operation.
+ */
+ public void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException {
+ if (!permitsImpl(cp.getCertificate().getPublicKey())) {
+ if (nextConstraint != null) {
+ nextConstraint.permits(cp);
+ return;
+ }
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on keysize limits",
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
+ }
+
+ // Check if key constraint disable the specified key
+ // Uses old style permit()
+ public boolean permits(Key key) {
+ // If we recursively find a constraint that permits us to use
+ // this key, return true and skip any other constraint checks.
+ if (nextConstraint != null && nextConstraint.permits(key)) {
+ return true;
+ }
+ if (debug != null) {
+ debug.println("KeySizeConstraints.permits(): " + algorithm);
+ }
+
+ return permitsImpl(key);
+ }
+
+ private boolean permitsImpl(Key key) {
+ // Verify this constraint is for this public key algorithm
+ if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
+ return true;
+ }
+
+ int size = KeyUtil.getKeySize(key);
if (size == 0) {
- return true; // we don't allow any key of size 0.
+ return false; // we don't allow any key of size 0.
} else if (size > 0) {
- return ((size < minSize) || (size > maxSize) ||
+ return !((size < minSize) || (size > maxSize) ||
(prohibitedSize == size));
} // Otherwise, the key size is not accessible. Conservatively,
// please don't disable such keys.
- return false;
+ return true;
}
}
-
}
--- a/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java Fri May 06 06:23:30 2016 -0700
@@ -196,8 +196,9 @@
// A new keystore is always created in the primary keystore format
if (stream == null) {
try {
- keystore = primaryKeyStore.newInstance();
-
+ @SuppressWarnings("deprecation")
+ KeyStoreSpi tmp = primaryKeyStore.newInstance();
+ keystore = tmp;
} catch (InstantiationException | IllegalAccessException e) {
// can safely ignore
}
@@ -214,7 +215,9 @@
bufferedStream.mark(Integer.MAX_VALUE);
try {
- keystore = primaryKeyStore.newInstance();
+ @SuppressWarnings("deprecation")
+ KeyStoreSpi tmp = primaryKeyStore.newInstance();
+ keystore = tmp;
type = primaryType;
keystore.engineLoad(bufferedStream, password);
@@ -232,7 +235,9 @@
throw e;
}
- keystore = secondaryKeyStore.newInstance();
+ @SuppressWarnings("deprecation")
+ KeyStoreSpi tmp= secondaryKeyStore.newInstance();
+ keystore = tmp;
type = secondaryType;
bufferedStream.reset();
keystore.engineLoad(bufferedStream, password);
@@ -284,7 +289,9 @@
boolean result = false;
try {
- keystore = primaryKeyStore.newInstance();
+ @SuppressWarnings("deprecation")
+ KeyStoreSpi tmp = primaryKeyStore.newInstance();
+ keystore = tmp;
type = primaryType;
result = keystore.engineProbe(stream);
--- a/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -28,8 +28,6 @@
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
import java.security.Key;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Set;
import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms;
@@ -42,15 +40,12 @@
public static final String PROPERTY_TLS_LEGACY_ALGS =
"jdk.tls.legacyAlgorithms";
- private static final Map<String, String[]> legacyAlgorithmsMap =
- new HashMap<>();
-
private final String[] legacyAlgorithms;
public LegacyAlgorithmConstraints(String propertyName,
AlgorithmDecomposer decomposer) {
super(decomposer);
- legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName);
+ legacyAlgorithms = getAlgorithms(propertyName);
}
@Override
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1924,17 +1924,18 @@
public String getFingerprint(String algorithm) {
return fingerprints.computeIfAbsent(algorithm,
- x -> getCertificateFingerPrint(x));
+ x -> getFingerprint(x, this));
}
/**
* Gets the requested finger print of the certificate. The result
* only contains 0-9 and A-F. No small case, no colon.
*/
- private String getCertificateFingerPrint(String mdAlg) {
+ public static String getFingerprint(String algorithm,
+ X509Certificate cert) {
try {
- byte[] encCertInfo = getEncoded();
- MessageDigest md = MessageDigest.getInstance(mdAlg);
+ byte[] encCertInfo = cert.getEncoded();
+ MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] digest = md.digest(encCertInfo);
StringBuilder sb = new StringBuilder(digest.length * 2);
for (int i = 0; i < digest.length; i++) {
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java Fri May 06 06:23:30 2016 -0700
@@ -255,11 +255,10 @@
}
}
- Object inst = null;
+ @SuppressWarnings("deprecation")
+ Object inst = (keyClass != null) ? keyClass.newInstance() : null;
X509Key result;
- if (keyClass != null)
- inst = keyClass.newInstance();
if (inst instanceof X509Key) {
result = (X509Key) inst;
result.algid = algid;
--- a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java Fri May 06 06:23:30 2016 -0700
@@ -157,8 +157,9 @@
cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName);
} else {
try {
- Class<?> cl = Class.forName(className);
- cal = (CalendarSystem) cl.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(className).newInstance();
+ cal = (CalendarSystem) tmp;
} catch (Exception e) {
throw new InternalError(e);
}
--- a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java Fri May 06 06:23:30 2016 -0700
@@ -144,7 +144,7 @@
// Append an era to the predefined eras if it's given by the property.
String prop = GetPropertyAction
- .getProperty("jdk.calendar.japanese.supplemental.era");
+ .privilegedGetProperty("jdk.calendar.japanese.supplemental.era");
if (prop != null) {
Era era = parseEraEntry(prop);
if (era != null) {
--- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java Fri May 06 06:23:30 2016 -0700
@@ -246,7 +246,7 @@
static {
String oldmapping = GetPropertyAction
- .getProperty("sun.timezone.ids.oldmapping", "false")
+ .privilegedGetProperty("sun.timezone.ids.oldmapping", "false")
.toLowerCase(Locale.ROOT);
USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true"));
AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Fri May 06 06:23:30 2016 -0700
@@ -116,7 +116,7 @@
adapterCache = new ConcurrentHashMap<>();
static {
- String order = GetPropertyAction.getProperty("java.locale.providers");
+ String order = GetPropertyAction.privilegedGetProperty("java.locale.providers");
List<Type> typeList = new ArrayList<>();
// Check user specified adapter preference
@@ -171,8 +171,9 @@
if (cached == null) {
try {
// lazily load adapters here
- adapter = (LocaleProviderAdapter)Class.forName(type.getAdapterClassName())
- .newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(type.getAdapterClassName()).newInstance();
+ adapter = (LocaleProviderAdapter)tmp;
cached = adapterInstances.putIfAbsent(type, adapter);
if (cached != null) {
adapter = cached;
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java Fri May 06 06:23:30 2016 -0700
@@ -73,7 +73,7 @@
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<P>() {
@Override
- @SuppressWarnings("unchecked")
+ @SuppressWarnings(value={"unchecked", "deprecation"})
public P run() {
P delegate = null;
--- a/jdk/src/java.base/share/conf/security/java.security Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/share/conf/security/java.security Fri May 06 06:23:30 2016 -0700
@@ -497,13 +497,13 @@
# " DisabledAlgorithm { , DisabledAlgorithm } "
#
# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+# AlgorithmName [Constraint] { '&' Constraint }
#
# AlgorithmName:
# (see below)
#
# Constraint:
-# KeySizeConstraint
+# KeySizeConstraint, CertConstraint
#
# KeySizeConstraint:
# keySize Operator DecimalInteger
@@ -520,6 +520,9 @@
# DecimalDigit: one of
# 1 2 3 4 5 6 7 8 9 0
#
+# CertConstraint
+# jdkCA
+#
# The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
# Documentation" for information about Standard Algorithm Names. Matching
@@ -542,6 +545,29 @@
# be disabled. Note that the "KeySizeConstraint" only makes sense to key
# algorithms.
#
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+# Â Â "jdkCA" prohibits the specified algorithm only if the algorithm is used
+# Â Â Â Â in a certificate chain that terminates at a marked trust anchor in the
+# Â Â Â Â lib/security/cacerts keystore. Â All other chains are not affected.
+# Â Â Â Â If the jdkCA constraint is not set, then all chains using the
+# Â Â Â Â specified algorithm are restricted. jdkCA may only be used once in
+# a DisabledAlgorithm expression.
+# Â Â Â Â Example: Â To apply this constraint to SHA-1 certificates, include
+# Â Â Â Â the following: Â "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'. For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint: "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property. This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm. For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
# Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations.
#
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java Fri May 06 06:23:30 2016 -0700
@@ -42,7 +42,7 @@
super(provider, dir);
// check os.version
- String osversion = GetPropertyAction.getProperty("os.version");
+ String osversion = GetPropertyAction.privilegedGetProperty("os.version");
String[] vers = Util.split(osversion, '.');
assert vers.length >= 2;
int majorVersion = Integer.parseInt(vers[0]);
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Fri May 06 06:23:30 2016 -0700
@@ -85,7 +85,7 @@
@Override
FileTypeDetector getFileTypeDetector() {
Path userMimeTypes = Paths.get(
- GetPropertyAction.getProperty("user.home"), ".mime.types");
+ GetPropertyAction.privilegedGetProperty("user.home"), ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
return chain(new GioFileTypeDetector(),
--- a/jdk/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, 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
@@ -94,6 +94,7 @@
return 0;
}
start = now;
+ a.dp_timeout = remaining;
}
} else {
return res;
--- a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java Fri May 06 06:23:30 2016 -0700
@@ -36,7 +36,7 @@
private final String javaHome;
public UnixFileSystem() {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
slash = props.getProperty("file.separator").charAt(0);
colon = props.getProperty("path.separator").charAt(0);
javaHome = props.getProperty("java.home");
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Fri May 06 06:23:30 2016 -0700
@@ -125,7 +125,7 @@
}
String helperPath() {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
return helperPath(props.getProperty("java.home"),
props.getProperty("os.arch"));
}
@@ -159,7 +159,7 @@
}
static Platform get() {
- String osName = GetPropertyAction.getProperty("os.name");
+ String osName = GetPropertyAction.privilegedGetProperty("os.name");
if (osName.equals("Linux")) { return LINUX; }
if (osName.contains("OS X")) { return BSD; }
--- a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java Fri May 06 06:23:30 2016 -0700
@@ -40,7 +40,7 @@
static {
String prefix = null;
try {
- prefix = GetPropertyAction.getProperty("impl.prefix", null);
+ prefix = GetPropertyAction.privilegedGetProperty("impl.prefix");
if (prefix != null)
prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
} catch (Exception e) {
@@ -61,7 +61,9 @@
throws SocketException {
if (prefixImplClass != null) {
try {
- return (DatagramSocketImpl)prefixImplClass.newInstance();
+ @SuppressWarnings("deprecation")
+ DatagramSocketImpl result = (DatagramSocketImpl)prefixImplClass.newInstance();
+ return result;
} catch (Exception e) {
throw new SocketException("can't instantiate DatagramSocketImpl");
}
--- a/jdk/src/java.base/unix/classes/sun/net/NetHooks.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/net/NetHooks.java Fri May 06 06:23:30 2016 -0700
@@ -28,9 +28,6 @@
import java.net.InetAddress;
import java.io.FileDescriptor;
import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetPropertyAction;
/**
* Defines static methods to be invoked prior to binding or connecting TCP sockets.
--- a/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java Fri May 06 06:23:30 2016 -0700
@@ -55,8 +55,9 @@
private PrintStream log;
public SdpProvider() {
+ Properties props = GetPropertyAction.privilegedGetProperties();
// if this property is not defined then there is nothing to do.
- String file = GetPropertyAction.getProperty("com.sun.sdp.conf");
+ String file = props.getProperty("com.sun.sdp.conf");
if (file == null) {
this.enabled = false;
this.rules = null;
@@ -65,17 +66,15 @@
// load configuration file
List<Rule> list = null;
- if (file != null) {
- try {
- list = loadRulesFromFile(file);
- } catch (IOException e) {
- fail("Error reading %s: %s", file, e.getMessage());
- }
+ try {
+ list = loadRulesFromFile(file);
+ } catch (IOException e) {
+ fail("Error reading %s: %s", file, e.getMessage());
}
// check if debugging is enabled
PrintStream out = null;
- String logfile = GetPropertyAction.getProperty("com.sun.sdp.debug");
+ String logfile = props.getProperty("com.sun.sdp.debug");
if (logfile != null) {
out = System.out;
if (logfile.length() > 0) {
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Fri May 06 06:23:30 2016 -0700
@@ -76,7 +76,7 @@
private String hostname;
/* Domain to use if not specified by user */
private static String defaultDomain =
- GetPropertyAction.getProperty("http.auth.ntlm.domain", "");
+ GetPropertyAction.privilegedGetProperty("http.auth.ntlm.domain", "");
public static boolean supportsTransparentAuth () {
return false;
@@ -141,7 +141,7 @@
password = pw.getPassword();
init0();
try {
- String version = GetPropertyAction.getProperty("ntlm.version");
+ String version = GetPropertyAction.privilegedGetProperty("ntlm.version");
client = new Client(version, hostname, username, ntdomain, password);
} catch (NTLMException ne) {
try {
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java Fri May 06 06:23:30 2016 -0700
@@ -48,7 +48,9 @@
throw new AssertionError(x);
}
try {
- return c.newInstance();
+ @SuppressWarnings("deprecation")
+ AsynchronousChannelProvider result = c.newInstance();
+ return result;
} catch (IllegalAccessException | InstantiationException x) {
throw new AssertionError(x);
}
@@ -59,7 +61,7 @@
* Returns the default AsynchronousChannelProvider.
*/
public static AsynchronousChannelProvider create() {
- String osname = GetPropertyAction.getProperty("os.name");
+ String osname = GetPropertyAction.privilegedGetProperty("os.name");
if (osname.equals("SunOS"))
return createProvider("sun.nio.ch.SolarisAsynchronousChannelProvider");
if (osname.equals("Linux"))
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Fri May 06 06:23:30 2016 -0700
@@ -46,8 +46,8 @@
private static final boolean disableSynchronousRead;
static {
- String propValue = GetPropertyAction
- .getProperty("sun.nio.ch.disableSynchronousRead", "false");
+ String propValue = GetPropertyAction.privilegedGetProperty(
+ "sun.nio.ch.disableSynchronousRead", "false");
disableSynchronousRead = (propValue.length() == 0) ?
true : Boolean.valueOf(propValue);
}
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java Fri May 06 06:23:30 2016 -0700
@@ -44,7 +44,9 @@
throw new AssertionError(x);
}
try {
- return c.newInstance();
+ @SuppressWarnings("deprecation")
+ FileSystemProvider result = c.newInstance();
+ return result;
} catch (IllegalAccessException | InstantiationException x) {
throw new AssertionError(x);
}
@@ -54,7 +56,7 @@
* Returns the default FileSystemProvider.
*/
public static FileSystemProvider create() {
- String osname = GetPropertyAction.getProperty("os.name");
+ String osname = GetPropertyAction.privilegedGetProperty("os.name");
if (osname.equals("SunOS"))
return createProvider("sun.nio.fs.SolarisFileSystemProvider");
if (osname.equals("Linux"))
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java Fri May 06 06:23:30 2016 -0700
@@ -57,7 +57,7 @@
// process working directory then paths must be resolved against the
// default directory.
String propValue = GetPropertyAction
- .getProperty("sun.nio.fs.chdirAllowed", "false");
+ .privilegedGetProperty("sun.nio.fs.chdirAllowed", "false");
boolean chdirAllowed = (propValue.length() == 0) ?
true : Boolean.valueOf(propValue);
if (chdirAllowed) {
--- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java Fri May 06 06:23:30 2016 -0700
@@ -42,7 +42,7 @@
private final char semicolon;
public WinNTFileSystem() {
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
slash = props.getProperty("file.separator").charAt(0);
semicolon = props.getProperty("path.separator").charAt(0);
altSlash = (this.slash == '\\') ? '/' : '\\';
--- a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java Fri May 06 06:23:30 2016 -0700
@@ -56,7 +56,7 @@
static {
Class<?> prefixImplClassLocal = null;
- Properties props = GetPropertyAction.getProperties();
+ Properties props = GetPropertyAction.privilegedGetProperties();
preferIPv4Stack = Boolean.parseBoolean(
props.getProperty("java.net.preferIPv4Stack"));
@@ -90,7 +90,9 @@
throws SocketException {
if (prefixImplClass != null) {
try {
- return (DatagramSocketImpl) prefixImplClass.newInstance();
+ @SuppressWarnings("deprecation")
+ Object result = prefixImplClass.newInstance();
+ return (DatagramSocketImpl) result;
} catch (Exception e) {
throw new SocketException("can't instantiate DatagramSocketImpl");
}
--- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Fri May 06 06:23:30 2016 -0700
@@ -53,8 +53,8 @@
private static String defaultDomain; /* Domain to use if not specified by user */
static {
- defaultDomain = GetPropertyAction.getProperty("http.auth.ntlm.domain",
- "domain");
+ defaultDomain = GetPropertyAction
+ .privilegedGetProperty("http.auth.ntlm.domain", "domain");
};
private void init0() {
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Fri May 06 06:23:30 2016 -0700
@@ -120,7 +120,7 @@
static boolean isFastFileTransferRequested() {
String fileTransferProp = GetPropertyAction
- .getProperty("jdk.nio.enableFastFileTransfer");
+ .privilegedGetProperty("jdk.nio.enableFastFileTransfer");
boolean enable;
if ("".equals(fileTransferProp)) {
enable = true;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Fri May 06 06:23:30 2016 -0700
@@ -114,8 +114,8 @@
// indicates if accurate metadata is required (interesting on NTFS only)
private static final boolean ensureAccurateMetadata;
static {
- String propValue = GetPropertyAction
- .getProperty("sun.nio.fs.ensureAccurateMetadata", "false");
+ String propValue = GetPropertyAction.privilegedGetProperty(
+ "sun.nio.fs.ensureAccurateMetadata", "false");
ensureAccurateMetadata = (propValue.length() == 0) ?
true : Boolean.valueOf(propValue);
}
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java Fri May 06 06:23:30 2016 -0700
@@ -113,6 +113,10 @@
// completion key (used to map I/O completion to WatchKey)
private int completionKey;
+ // flag indicates that ReadDirectoryChangesW failed
+ // and overlapped I/O operation wasn't started
+ private boolean errorStartingOverlapped;
+
WindowsWatchKey(Path dir,
AbstractWatchService watcher,
FileKey fileKey)
@@ -175,6 +179,14 @@
return completionKey;
}
+ void setErrorStartingOverlapped(boolean value) {
+ errorStartingOverlapped = value;
+ }
+
+ boolean isErrorStartingOverlapped() {
+ return errorStartingOverlapped;
+ }
+
// Invalidate the key, assumes that resources have been released
void invalidate() {
((WindowsWatchService)watcher()).poller.releaseResources(this);
@@ -182,6 +194,7 @@
buffer = null;
countAddress = 0;
overlappedAddress = 0;
+ errorStartingOverlapped = false;
}
@Override
@@ -455,11 +468,13 @@
* resources.
*/
private void releaseResources(WindowsWatchKey key) {
- try {
- CancelIo(key.handle());
- GetOverlappedResult(key.handle(), key.overlappedAddress());
- } catch (WindowsException expected) {
- // expected as I/O operation has been cancelled
+ if (!key.isErrorStartingOverlapped()) {
+ try {
+ CancelIo(key.handle());
+ GetOverlappedResult(key.handle(), key.overlappedAddress());
+ } catch (WindowsException expected) {
+ // expected as I/O operation has been cancelled
+ }
}
CloseHandle(key.handle());
closeAttachedEvent(key.overlappedAddress());
@@ -628,6 +643,7 @@
} catch (WindowsException x) {
// no choice but to cancel key
criticalError = true;
+ key.setErrorStartingOverlapped(true);
}
}
if (criticalError) {
--- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Fri May 06 06:23:30 2016 -0700
@@ -83,7 +83,7 @@
// if we have no foreground frames, then we have to "kick" the menubar
final JFrame pingFrame = new JFrame();
- pingFrame.getRootPane().putClientProperty("Window.alpha", new Float(0.0f));
+ pingFrame.getRootPane().putClientProperty("Window.alpha", Float.valueOf(0.0f));
pingFrame.setUndecorated(true);
pingFrame.setVisible(true);
pingFrame.toFront();
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java Fri May 06 06:23:30 2016 -0700
@@ -58,7 +58,7 @@
updateContents(false);
// TODO: CPlatformWindow?
- putClientProperty(CPlatformWindow.WINDOW_FADE_OUT, new Integer(150));
+ putClientProperty(CPlatformWindow.WINDOW_FADE_OUT, Integer.valueOf(150));
}
public void updateContents(final boolean remove) {
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -91,7 +91,7 @@
JComponent getDock() {
if (fDock == null) {
fDock = new Dock(desktop);
- desktop.add(fDock, new Integer(399)); // Just below the DRAG_LAYER
+ desktop.add(fDock, Integer.valueOf(399)); // Just below the DRAG_LAYER
}
return fDock;
}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java Fri May 06 06:23:30 2016 -0700
@@ -416,7 +416,7 @@
"Button.select", selected,
"Button.border",(LazyValue) t -> AquaButtonBorder.getDynamicButtonBorder(),
"Button.font", controlFont,
- "Button.textIconGap", new Integer(4),
+ "Button.textIconGap", Integer.valueOf(4),
"Button.textShiftOffset", zero, // radar 3308129 - aqua doesn't move images when pressed.
"Button.focusInputMap", controlFocusInputMap,
"Button.margin", new InsetsUIResource(0, 2, 0, 2),
@@ -635,8 +635,8 @@
//"Menu.checkIcon", emptyCheckIcon, // A non-drawing GlyphIcon to make the spacing consistent
"Menu.arrowIcon",(LazyValue) t -> AquaImageFactory.getMenuArrowIcon(),
"Menu.consumesTabs", Boolean.TRUE,
- "Menu.menuPopupOffsetY", new Integer(1),
- "Menu.submenuPopupOffsetY", new Integer(-4),
+ "Menu.menuPopupOffsetY", Integer.valueOf(1),
+ "Menu.submenuPopupOffsetY", Integer.valueOf(-4),
"MenuBar.font", menuFont,
"MenuBar.background", menuBackgroundColor, // not a menu item, not selected
@@ -694,7 +694,7 @@
"OptionPane.informationSound", null, // Info and Plain
"OptionPane.questionSound", null,
"OptionPane.warningSound", null,
- "OptionPane.buttonClickThreshhold", new Integer(500),
+ "OptionPane.buttonClickThreshhold", Integer.valueOf(500),
"OptionPane.yesButtonMnemonic", "",
"OptionPane.noButtonMnemonic", "",
"OptionPane.okButtonMnemonic", "",
@@ -717,7 +717,7 @@
"PasswordField.caretBlinkRate", textCaretBlinkRate,
"PasswordField.border", textFieldBorder,
"PasswordField.margin", zeroInsets,
- "PasswordField.echoChar", new Character((char)0x25CF),
+ "PasswordField.echoChar", Character.valueOf((char)0x25CF),
"PasswordField.capsLockIconColor", textPasswordFieldCapsLockIconColor,
"PopupMenu.font", menuFont,
@@ -736,7 +736,7 @@
"ProgressBar.selectionForeground", black,
"ProgressBar.selectionBackground", white,
"ProgressBar.border", new BorderUIResource(BorderFactory.createEmptyBorder()),
- "ProgressBar.repaintInterval", new Integer(20),
+ "ProgressBar.repaintInterval", Integer.valueOf(20),
"RadioButton.background", controlBackgroundColor,
"RadioButton.foreground", black,
@@ -772,7 +772,7 @@
"ScrollBar.border", null,
"ScrollBar.focusInputMap", aquaKeyBindings.getScrollBarInputMap(),
"ScrollBar.focusInputMap.RightToLeft", aquaKeyBindings.getScrollBarRightToLeftInputMap(),
- "ScrollBar.width", new Integer(16),
+ "ScrollBar.width", Integer.valueOf(16),
"ScrollBar.background", white,
"ScrollBar.foreground", black,
@@ -816,7 +816,7 @@
//"SplitPane.shadow", table.get("controlShadow"),
"SplitPane.background", panelBackgroundColor,
"SplitPane.border", scollListBorder,
- "SplitPane.dividerSize", new Integer(9), //$
+ "SplitPane.dividerSize", Integer.valueOf(9), //$
"SplitPaneDivider.border", null, // AquaSplitPaneDividerUI draws it
"SplitPaneDivider.horizontalGradientVariant",(LazyValue) t -> AquaSplitPaneDividerUI.getHorizontalSplitDividerGradientVariant(),
@@ -833,7 +833,7 @@
//"TabbedPane.darkShadow", table.get("controlDkShadow"),
//"TabbedPane.focus", table.get("controlText"),
"TabbedPane.opaque", useOpaqueComponents,
- "TabbedPane.textIconGap", new Integer(4),
+ "TabbedPane.textIconGap", Integer.valueOf(4),
"TabbedPane.tabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab (top, left, bottom, right)
//"TabbedPane.rightTabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab (top, left, bottom, right)
"TabbedPane.leftTabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab
@@ -973,9 +973,9 @@
"Tree.selectionBorderColor", selectionBackground, // match the background so it looks like we don't draw anything
"Tree.editorBorderSelectionColor", null, // The EditTextFrame provides its own border
// "Tree.editorBorder", textFieldBorder, // If you still have Sun bug 4376328 in DefaultTreeCellEditor, it has to have the same insets as TextField.border
- "Tree.leftChildIndent", new Integer(7),//$
- "Tree.rightChildIndent", new Integer(13),//$
- "Tree.rowHeight", new Integer(19),// iconHeight + 3, to match finder - a zero would have the renderer decide, except that leaves the icons touching
+ "Tree.leftChildIndent", Integer.valueOf(7),//$
+ "Tree.rightChildIndent", Integer.valueOf(13),//$
+ "Tree.rowHeight", Integer.valueOf(19),// iconHeight + 3, to match finder - a zero would have the renderer decide, except that leaves the icons touching
"Tree.scrollsOnExpand", Boolean.FALSE,
"Tree.openIcon",(LazyValue) t -> AquaImageFactory.getTreeOpenFolderIcon(), // Open folder icon
"Tree.closedIcon",(LazyValue) t -> AquaImageFactory.getTreeFolderIcon(), // Closed folder icon
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Fri May 06 06:23:30 2016 -0700
@@ -521,7 +521,7 @@
}
// [2165820] Mac OS X change: mnemonics need to be triggered with ctrl-option, not just option.
mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK | Event.CTRL_MASK), "setSelectedIndex");
- mnemonicToIndexMap.put(new Integer(mnemonic), new Integer(index));
+ mnemonicToIndexMap.put(Integer.valueOf(mnemonic), Integer.valueOf(index));
}
/**
@@ -2084,7 +2084,7 @@
if (mnemonic >= 'a' && mnemonic <= 'z') {
mnemonic -= ('a' - 'A');
}
- final Integer index = ui.mnemonicToIndexMap.get(new Integer(mnemonic));
+ final Integer index = ui.mnemonicToIndexMap.get(Integer.valueOf(mnemonic));
if (index != null && pane.isEnabledAt(index.intValue())) {
pane.setSelectedIndex(index.intValue());
}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java Fri May 06 06:23:30 2016 -0700
@@ -268,7 +268,7 @@
public SizeVariant alterFontSize(final float newSize) {
final float oldSize = fontSize == null ? 0.0f : fontSize.floatValue();
- fontSize = new Float(newSize + oldSize);
+ fontSize = newSize + oldSize;
return this;
}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java Fri May 06 06:23:30 2016 -0700
@@ -32,8 +32,8 @@
import sun.swing.SwingAccessor;
class ScreenPopupFactory extends PopupFactory {
- static final Float TRANSLUCENT = new Float(248f/255f);
- static final Float OPAQUE = new Float(1.0f);
+ static final Float TRANSLUCENT = 248f/255f;
+ static final Float OPAQUE = 1.0f;
boolean fIsActive = true;
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java Fri May 06 06:23:30 2016 -0700
@@ -386,7 +386,7 @@
if (generalCache == null) {
return 0L;
}
- final Long value = generalCache.get(new Integer(index));
+ final Long value = generalCache.get(Integer.valueOf(index));
if (value == null) {
return 0L;
}
@@ -415,7 +415,7 @@
generalCache = new HashMap<Integer, Long>();
}
- generalCache.put(new Integer(index), Long.valueOf(value));
+ generalCache.put(Integer.valueOf(index), Long.valueOf(value));
}
public synchronized void dispose() {
@@ -526,7 +526,7 @@
}
if (generalCache == null) return 0;
- final Float value = generalCache.get(new Integer(index));
+ final Float value = generalCache.get(Integer.valueOf(index));
if (value == null) return 0;
return value.floatValue();
}
@@ -553,7 +553,7 @@
generalCache = new HashMap<Integer, Float>();
}
- generalCache.put(new Integer(index), new Float(value));
+ generalCache.put(Integer.valueOf(index), Float.valueOf(value));
}
private static class SparseBitShiftingTwoLayerArray {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, 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
@@ -903,7 +903,7 @@
@Override
public boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
@@ -1278,7 +1278,7 @@
assert (e.getSource() == target);
if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
- LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
+ LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,8 +31,8 @@
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.dnd.DropTarget;
+import java.awt.event.FocusEvent;
-import sun.awt.CausedFocusEvent;
import sun.awt.LightweightFrame;
import sun.swing.JLightweightFrame;
import sun.swing.SwingAccessor;
@@ -60,7 +60,7 @@
}
@Override
- public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
+ public boolean requestWindowFocus(FocusEvent.Cause cause) {
if (!focusAllowedFor()) {
return false;
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java Fri May 06 06:23:30 2016 -0700
@@ -404,6 +404,10 @@
public final PrintJob getPrintJob(Frame frame, String doctitle,
JobAttributes jobAttributes,
PageAttributes pageAttributes) {
+ if (frame == null) {
+ throw new NullPointerException("frame must not be null");
+ }
+
if (GraphicsEnvironment.isHeadless()) {
throw new IllegalArgumentException();
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -256,14 +256,14 @@
if (!getTarget().isAutoRequestFocus()) {
return;
} else {
- requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION);
+ requestWindowFocus(FocusEvent.Cause.ACTIVATION);
}
// Focus the owner in case this window is focused.
} else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) {
// Transfer focus to the owner.
LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this);
if (owner != null) {
- owner.requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION);
+ owner.requestWindowFocus(FocusEvent.Cause.ACTIVATION);
}
}
}
@@ -295,7 +295,7 @@
if (f == null) {
f = DEFAULT_FONT;
}
- return platformWindow.transformGraphics(new SunGraphics2D(getSurfaceData(), fg, bg, f));
+ return new SunGraphics2D(getSurfaceData(), fg, bg, f);
}
@Override
@@ -848,7 +848,7 @@
// 2. An active but not focused owner frame/dialog is clicked.
// The mouse event then will trigger a focus request "in window" to the component, so the window
// should gain focus before.
- requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT);
+ requestWindowFocus(FocusEvent.Cause.MOUSE_EVENT);
mouseDownTarget[targetIdx] = targetPeer;
} else if (id == MouseEvent.MOUSE_DRAGGED) {
@@ -1199,7 +1199,7 @@
* Requests platform to set native focus on a frame/dialog.
* In case of a simple window, triggers appropriate java focus change.
*/
- public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
+ public boolean requestWindowFocus(FocusEvent.Cause cause) {
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("requesting native focus to " + this);
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -26,8 +26,8 @@
package sun.lwawt;
import java.awt.*;
+import java.awt.event.FocusEvent;
-import sun.awt.CausedFocusEvent;
import sun.java2d.SurfaceData;
// TODO Is it worth to generify this interface, like that:
@@ -114,7 +114,7 @@
public void updateFocusableWindowState();
- public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
+ public boolean rejectFocusRequest(FocusEvent.Cause cause);
public boolean requestWindowFocus();
@@ -130,12 +130,6 @@
*/
public void setSizeConstraints(int minW, int minH, int maxW, int maxH);
- /**
- * Transforms the given Graphics object according to the native
- * implementation traits (insets, etc.).
- */
- public Graphics transformGraphics(Graphics g);
-
/*
* Installs the images for particular window.
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/AccessibilityEventMonitor.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,253 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.lwawt.macosx;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.swing.event.EventListenerList;
+
+/**
+ * <P>{@code AccessibilityEventMonitor} implements a PropertyChange listener
+ * on every UI object that implements interface {@code Accessible} in the Java
+ * Virtual Machine. The events captured by these listeners are made available
+ * through listeners supported by {@code AccessibilityEventMonitor}.
+ * With this, all the individual events on each of the UI object
+ * instances are funneled into one set of PropertyChange listeners.
+ *
+ * This code is a subset of com.sun.java.accessibility.util.AccessibilityEventMonitor
+ * which resides in module jdk.accessibility. Due to modularization the code in
+ * this package, java.desktop, can not be dependent on code in jdk.accessibility.
+ */
+
+class AccessibilityEventMonitor {
+
+ /**
+ * The current list of registered {@link java.beans.PropertyChangeListener
+ * PropertyChangeListener} classes.
+ *
+ * @see #addPropertyChangeListener
+ */
+ private static final EventListenerList listenerList =
+ new EventListenerList();
+
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ */
+ private static final AccessibilityEventListener accessibilityListener =
+ new AccessibilityEventListener();
+
+ /**
+ * Adds the specified listener to receive all PropertyChange events on
+ * each UI object instance in the Java Virtual Machine as they occur.
+ * <P>Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to UI object instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @param a the Accessible object to add the PropertyChangeListener to
+ */
+
+ static void addPropertyChangeListener(PropertyChangeListener l, Accessible a) {
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ accessibilityListener.installListeners(a);
+ }
+ listenerList.add(PropertyChangeListener.class, l);
+ }
+
+ /**
+ * AccessibilityEventListener is the class that does all the work for
+ * AccessibilityEventMonitor. It is not intended for use by any other
+ * class except AccessibilityEventMonitor.
+ */
+
+ private static class AccessibilityEventListener implements PropertyChangeListener {
+
+ /**
+ * Installs PropertyChange listeners to the Accessible object, and its
+ * children (so long as the object isn't of TRANSIENT state).
+ *
+ * @param a the Accessible object to add listeners to
+ */
+ private void installListeners(Accessible a) {
+ installListeners(a.getAccessibleContext());
+ }
+
+ /**
+ * Installs PropertyChange listeners to the AccessibleContext object,
+ * and its * children (so long as the object isn't of TRANSIENT state).
+ *
+ * @param ac the AccessibleContext to add listeners to
+ */
+ private void installListeners(AccessibleContext ac) {
+
+ if (ac != null) {
+ AccessibleStateSet states = ac.getAccessibleStateSet();
+ if (!states.contains(AccessibleState.TRANSIENT)) {
+ ac.addPropertyChangeListener(this);
+ /*
+ * Don't add listeners to transient children. Components
+ * with transient children should return an AccessibleStateSet
+ * containing AccessibleState.MANAGES_DESCENDANTS. Components
+ * may not explicitly return the MANAGES_DESCENDANTS state.
+ * In this case, don't add listeners to the children of
+ * lists, tables and trees.
+ */
+ AccessibleStateSet set = ac.getAccessibleStateSet();
+ if (set.contains(AccessibleState.MANAGES_DESCENDANTS)) {
+ return;
+ }
+ AccessibleRole role = ac.getAccessibleRole();
+ if ( role == AccessibleRole.LIST ||
+ role == AccessibleRole.TREE ) {
+ return;
+ }
+ if (role == AccessibleRole.TABLE) {
+ // handle Oracle tables containing tables
+ Accessible child = ac.getAccessibleChild(0);
+ if (child != null) {
+ AccessibleContext ac2 = child.getAccessibleContext();
+ if (ac2 != null) {
+ role = ac2.getAccessibleRole();
+ if (role != null && role != AccessibleRole.TABLE) {
+ return;
+ }
+ }
+ }
+ }
+ int count = ac.getAccessibleChildrenCount();
+ for (int i = 0; i < count; i++) {
+ Accessible child = ac.getAccessibleChild(i);
+ if (child != null) {
+ installListeners(child);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes PropertyChange listeners for the given Accessible object,
+ * its children (so long as the object isn't of TRANSIENT state).
+ *
+ * @param a the Accessible object to remove listeners from
+ */
+ private void removeListeners(Accessible a) {
+ removeListeners(a.getAccessibleContext());
+ }
+
+ /**
+ * Removes PropertyChange listeners for the given AccessibleContext
+ * object, its children (so long as the object isn't of TRANSIENT
+ * state).
+ *
+ * @param a the Accessible object to remove listeners from
+ */
+ private void removeListeners(AccessibleContext ac) {
+
+ if (ac != null) {
+ // Listeners are not added to transient components.
+ AccessibleStateSet states = ac.getAccessibleStateSet();
+ if (!states.contains(AccessibleState.TRANSIENT)) {
+ ac.removePropertyChangeListener(this);
+ /*
+ * Listeners are not added to transient children. Components
+ * with transient children should return an AccessibleStateSet
+ * containing AccessibleState.MANAGES_DESCENDANTS. Components
+ * may not explicitly return the MANAGES_DESCENDANTS state.
+ * In this case, don't remove listeners from the children of
+ * lists, tables and trees.
+ */
+ if (states.contains(AccessibleState.MANAGES_DESCENDANTS)) {
+ return;
+ }
+ AccessibleRole role = ac.getAccessibleRole();
+ if ( role == AccessibleRole.LIST ||
+ role == AccessibleRole.TABLE ||
+ role == AccessibleRole.TREE ) {
+ return;
+ }
+ int count = ac.getAccessibleChildrenCount();
+ for (int i = 0; i < count; i++) {
+ Accessible child = ac.getAccessibleChild(i);
+ if (child != null) {
+ removeListeners(child);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent e) {
+ // propogate the event
+ Object[] listeners =
+ AccessibilityEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PropertyChangeListener.class) {
+ ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
+ }
+ }
+
+ // handle childbirth/death
+ String name = e.getPropertyName();
+ if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
+ Object oldValue = e.getOldValue();
+ Object newValue = e.getNewValue();
+
+ if ((oldValue == null) ^ (newValue == null)) { // one null, not both
+ if (oldValue != null) {
+ // this Accessible is a child that's going away
+ if (oldValue instanceof Accessible) {
+ Accessible a = (Accessible) oldValue;
+ removeListeners(a.getAccessibleContext());
+ } else if (oldValue instanceof AccessibleContext) {
+ removeListeners((AccessibleContext) oldValue);
+ }
+ } else if (newValue != null) {
+ // this Accessible is a child was just born
+ if (newValue instanceof Accessible) {
+ Accessible a = (Accessible) newValue;
+ installListeners(a.getAccessibleContext());
+ } else if (newValue instanceof AccessibleContext) {
+ installListeners((AccessibleContext) newValue);
+ }
+ }
+ } else {
+ System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString());
+ }
+ }
+ }
+ }
+}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -25,12 +25,15 @@
package sun.lwawt.macosx;
+import sun.lwawt.LWWindowPeer;
+
import java.awt.*;
import java.beans.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.Callable;
+import sun.awt.AWTAccessor;
import javax.accessibility.*;
import javax.swing.*;
@@ -421,6 +424,8 @@
}
public static AccessibleAction getAccessibleAction(final Accessible a, final Component c) {
+ if (a == null) return null;
+
return invokeAndWait(new Callable<AccessibleAction>() {
public AccessibleAction call() throws Exception {
final AccessibleContext ac = a.getAccessibleContext();
@@ -667,4 +672,28 @@
}
}, c);
}
+
+ /**
+ * @return AWTView ptr, a peer of the CPlatformView associated with the toplevel container of the Accessible, if any
+ */
+ private static long getAWTView(Accessible a) {
+ Accessible ax = CAccessible.getSwingAccessible(a);
+ if (!(ax instanceof Component)) return 0;
+
+ return invokeAndWait(new Callable<Long>() {
+ public Long call() throws Exception {
+ Component cont = (Component) ax;
+ while (cont != null && !(cont instanceof Window)) {
+ cont = cont.getParent();
+ }
+ if (cont != null) {
+ LWWindowPeer peer = (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(cont);
+ if (peer != null) {
+ return ((CPlatformWindow) peer.getPlatformWindow()).getContentView().getAWTView();
+ }
+ }
+ return 0L;
+ }
+ }, (Component)ax);
+ }
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,20 +26,18 @@
package sun.lwawt.macosx;
import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
-import javax.swing.event.CaretEvent;
-import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.JTextComponent;
+import sun.lwawt.macosx.CFRetainedResource;
class CAccessible extends CFRetainedResource implements Accessible {
static Field getNativeAXResourceField() {
@@ -99,13 +97,10 @@
return accessible.getAccessibleContext();
}
- // currently only supports text components
public void addNotificationListeners(Component c) {
- if (c instanceof JTextComponent) {
- JTextComponent tc = (JTextComponent) c;
- AXTextChangeNotifier listener = new AXTextChangeNotifier();
- tc.getDocument().addDocumentListener(listener);
- tc.addCaretListener(listener);
+ AXTextChangeNotifier listener = new AXTextChangeNotifier();
+ if (c instanceof Accessible) {
+ AccessibilityEventMonitor.addPropertyChangeListener(listener, (Accessible)c);
}
if (c instanceof JProgressBar) {
JProgressBar pb = (JProgressBar) c;
@@ -117,29 +112,23 @@
}
- private class AXTextChangeNotifier implements DocumentListener, CaretListener {
- @Override
- public void changedUpdate(DocumentEvent e) {
- if (ptr != 0) valueChanged(ptr);
- }
+ private class AXTextChangeNotifier implements PropertyChangeListener {
@Override
- public void insertUpdate(DocumentEvent e) {
- if (ptr != 0) valueChanged(ptr);
- }
-
- @Override
- public void removeUpdate(DocumentEvent e) {
- if (ptr != 0) valueChanged(ptr);
- }
-
- @Override
- public void caretUpdate(CaretEvent e) {
- if (ptr != 0) selectionChanged(ptr);
+ public void propertyChange(PropertyChangeEvent e) {
+ String name = e.getPropertyName();
+ if ( ptr != 0 ) {
+ if (name.compareTo(AccessibleContext.ACCESSIBLE_CARET_PROPERTY) == 0) {
+ selectionChanged(ptr);
+ } else if (name.compareTo(AccessibleContext.ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
+ valueChanged(ptr);
+ }
+ }
}
}
private class AXProgressChangeNotifier implements ChangeListener {
+ @Override
public void stateChanged(ChangeEvent e) {
if (ptr != 0) valueChanged(ptr);
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -264,6 +264,8 @@
final double localY = boundsUnion.getY();
final Point componentLocation = ac.getAccessibleComponent().getLocationOnScreen();
+ if (componentLocation == null) return ret;
+
final double screenX = componentLocation.getX() + localX;
final double screenY = componentLocation.getY() + localY;
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -26,6 +26,7 @@
package sun.lwawt.macosx;
import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
import java.awt.peer.*;
import java.awt.BufferCapabilities.FlipContents;
import java.awt.event.*;
@@ -34,7 +35,6 @@
import java.util.List;
import java.io.*;
-import sun.awt.CausedFocusEvent.Cause;
import sun.awt.AWTAccessor;
import sun.java2d.pipe.Region;
import sun.security.action.GetBooleanAction;
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -26,11 +26,11 @@
package sun.lwawt.macosx;
import java.awt.*;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent;
+
import sun.java2d.SurfaceData;
import sun.java2d.opengl.CGLLayer;
import sun.lwawt.LWWindowPeer;
-import sun.lwawt.LWWindowPeer.PeerType;
import sun.lwawt.PlatformWindow;
import sun.util.logging.PlatformLogger;
@@ -39,7 +39,8 @@
*/
public class CPlatformEmbeddedFrame implements PlatformWindow {
- private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
+ private static final PlatformLogger focusLogger = PlatformLogger.getLogger(
+ "sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
private CGLLayer windowLayer;
private LWWindowPeer peer;
@@ -133,9 +134,9 @@
public void updateFocusableWindowState() {}
@Override
- public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+ public boolean rejectFocusRequest(FocusEvent.Cause cause) {
// Cross-app activation requests are not allowed.
- if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+ if (cause != FocusEvent.Cause.MOUSE_EVENT &&
!target.isParentWindowActive())
{
focusLogger.fine("the embedder is inactive, so the request is rejected");
@@ -161,11 +162,6 @@
public void setSizeConstraints(int minW, int minH, int maxW, int maxH) {}
@Override
- public Graphics transformGraphics(Graphics g) {
- return g;
- }
-
- @Override
public void updateIconImages() {}
@Override
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -27,7 +27,6 @@
import java.awt.Font;
import java.awt.FontMetrics;
-import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
@@ -37,7 +36,7 @@
import java.awt.Window;
import sun.awt.CGraphicsDevice;
import sun.awt.CGraphicsEnvironment;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent;
import sun.awt.LightweightFrame;
import sun.java2d.SurfaceData;
import sun.lwawt.LWLightweightFramePeer;
@@ -134,7 +133,7 @@
}
@Override
- public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+ public boolean rejectFocusRequest(FocusEvent.Cause cause) {
return false;
}
@@ -153,11 +152,6 @@
}
@Override
- public Graphics transformGraphics(Graphics g) {
- return null;
- }
-
- @Override
public void setAlwaysOnTop(boolean isAlwaysOnTop) {
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -706,9 +706,9 @@
}
@Override
- public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+ public boolean rejectFocusRequest(FocusEvent.Cause cause) {
// Cross-app activation requests are not allowed.
- if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+ if (cause != FocusEvent.Cause.MOUSE_EVENT &&
!((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
{
focusLogger.fine("the app is inactive, so the request is rejected");
@@ -741,12 +741,6 @@
}
@Override
- public Graphics transformGraphics(Graphics g) {
- // is this where we can inject a transform for HiDPI?
- return g;
- }
-
- @Override
public void setAlwaysOnTop(boolean isAlwaysOnTop) {
setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri May 06 06:23:30 2016 -0700
@@ -98,15 +98,26 @@
private native long nativeCreate();
//invocation from the AWTTrayIcon.m
- public long getPopupMenuModel(){
- if(popup == null) {
- PopupMenu popupMenu = target.getPopupMenu();
- if (popupMenu != null) {
- popup = popupMenu;
+ public long getPopupMenuModel() {
+ PopupMenu newPopup = target.getPopupMenu();
+
+ if (popup == newPopup) {
+ if (popup == null) {
+ return 0L;
+ }
+ } else {
+ if (newPopup != null) {
+ if (popup != null) {
+ popup.removeNotify();
+ popup = newPopup;
+ } else {
+ popup = newPopup;
+ }
} else {
return 0L;
}
}
+
return checkAndCreatePopupPeer().getModel();
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Fri May 06 06:23:30 2016 -0700
@@ -87,23 +87,22 @@
}
}
- /*
+ /**
* Initializes the embedded frame bounds and validates a component.
- * Designed to be called from the main thread
- * This method should be called once from the initialization of the SWT_AWT Bridge
+ * Designed to be called from the main thread. This method should be called
+ * once from the initialization of the SWT_AWT Bridge.
*/
- public void validateWithBounds(final int x, final int y, final int width, final int height) {
+ public void validateWithBounds(final int x, final int y, final int width,
+ final int height) {
try {
- final LWWindowPeer peer = AWTAccessor.getComponentAccessor()
- .getPeer(this);
- LWCToolkit.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- peer.setBoundsPrivate(0, 0, width, height);
- validate();
- setVisible(true);
- }
+ LWCToolkit.invokeAndWait(() -> {
+ final LWWindowPeer peer = AWTAccessor.getComponentAccessor()
+ .getPeer(this);
+ peer.setBoundsPrivate(0, 0, width, height);
+ validate();
+ setVisible(true);
}, this);
- } catch (InvocationTargetException ex) {}
+ } catch (InvocationTargetException ex) {
+ }
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,13 +27,12 @@
import java.awt.Font;
import java.awt.FontMetrics;
-import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.Insets;
import java.awt.MenuBar;
import java.awt.Point;
import java.awt.Window;
-import sun.awt.CausedFocusEvent.Cause;
+import java.awt.event.FocusEvent.Cause;
import sun.java2d.SurfaceData;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformWindow;
@@ -171,11 +170,6 @@
}
@Override
- public Graphics transformGraphics(Graphics g) {
- return g;
- }
-
- @Override
public void updateIconImages() {
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -364,8 +364,8 @@
return null;
}
- return transformGraphics(new SunGraphics2D(sd, SystemColor.windowText,
- SystemColor.window, ownerWindow.getFont()));
+ return new SunGraphics2D(sd, SystemColor.windowText, SystemColor.window,
+ ownerWindow.getFont());
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Fri May 06 06:23:30 2016 -0700
@@ -378,9 +378,9 @@
// These DnD properties must be set, otherwise Swing ends up spewing NPEs
// all over the place. The values came straight off of MToolkit.
- desktopProperties.put("DnD.Autoscroll.initialDelay", new Integer(50));
- desktopProperties.put("DnD.Autoscroll.interval", new Integer(50));
- desktopProperties.put("DnD.Autoscroll.cursorHysteresis", new Integer(5));
+ desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50));
+ desktopProperties.put("DnD.Autoscroll.interval", Integer.valueOf(50));
+ desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5));
desktopProperties.put("DnD.isDragImageSupported", Boolean.TRUE);
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.h Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -62,6 +62,8 @@
- (void) deliverJavaMouseEvent: (NSEvent *) event;
- (jobject) awtComponent:(JNIEnv *)env;
++ (AWTView *) awtView:(JNIEnv *)env ofAccessible:(jobject)jaccessible;
+
// Input method-related events
- (void)setInputMethod:(jobject)inputMethod;
- (void)abandonInput;
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Fri May 06 06:23:30 2016 -0700
@@ -29,6 +29,7 @@
#import "AWTWindow.h"
#import "JavaComponentAccessibility.h"
#import "JavaTextAccessibility.h"
+#import "JavaAccessibilityUtilities.h"
#import "GeomUtilities.h"
#import "OSVersion.h"
#import "ThreadUtilities.h"
@@ -129,7 +130,7 @@
self.cglLayer = nil;
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
- (*env)->DeleteGlobalRef(env, m_cPlatformView);
+ (*env)->DeleteWeakGlobalRef(env, m_cPlatformView);
m_cPlatformView = NULL;
if (fInputMethodLOCKABLE != NULL)
@@ -396,7 +397,11 @@
static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView");
static JNF_MEMBER_CACHE(jm_deliverMouseEvent, jc_PlatformView, "deliverMouseEvent", "(Lsun/lwawt/macosx/NSEvent;)V");
- JNFCallVoidMethod(env, m_cPlatformView, jm_deliverMouseEvent, jEvent);
+ jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView);
+ if (!(*env)->IsSameObject(env, jlocal, NULL)) {
+ JNFCallVoidMethod(env, jlocal, jm_deliverMouseEvent, jEvent);
+ (*env)->DeleteLocalRef(env, jlocal);
+ }
(*env)->DeleteLocalRef(env, jEvent);
}
@@ -459,8 +464,11 @@
static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView");
static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_PlatformView,
"deliverKeyEvent", "(Lsun/lwawt/macosx/NSEvent;)V");
- JNFCallVoidMethod(env, m_cPlatformView, jm_deliverKeyEvent, jEvent);
-
+ jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView);
+ if (!(*env)->IsSameObject(env, jlocal, NULL)) {
+ JNFCallVoidMethod(env, jlocal, jm_deliverKeyEvent, jEvent);
+ (*env)->DeleteLocalRef(env, jlocal);
+ }
if (characters != NULL) {
(*env)->DeleteLocalRef(env, characters);
}
@@ -475,7 +483,12 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView");
static JNF_MEMBER_CACHE(jm_deliverResize, jc_PlatformView, "deliverResize", "(IIII)V");
- JNFCallVoidMethod(env, m_cPlatformView, jm_deliverResize, x,y,w,h);
+
+ jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView);
+ if (!(*env)->IsSameObject(env, jlocal, NULL)) {
+ JNFCallVoidMethod(env, jlocal, jm_deliverResize, x,y,w,h);
+ (*env)->DeleteLocalRef(env, jlocal);
+ }
}
@@ -504,7 +517,11 @@
*/
static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView");
static JNF_MEMBER_CACHE(jm_deliverWindowDidExposeEvent, jc_CPlatformView, "deliverWindowDidExposeEvent", "()V");
- JNFCallVoidMethod(env, m_cPlatformView, jm_deliverWindowDidExposeEvent);
+ jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView);
+ if (!(*env)->IsSameObject(env, jlocal, NULL)) {
+ JNFCallVoidMethod(env, jlocal, jm_deliverWindowDidExposeEvent);
+ (*env)->DeleteLocalRef(env, jlocal);
+ }
/*
}
*/
@@ -541,7 +558,13 @@
}
return NULL;
}
- jobject peer = JNFGetObjectField(env, m_cPlatformView, jf_Peer);
+
+ jobject peer = NULL;
+ jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView);
+ if (!(*env)->IsSameObject(env, jlocal, NULL)) {
+ peer = JNFGetObjectField(env, jlocal, jf_Peer);
+ (*env)->DeleteLocalRef(env, jlocal);
+ }
static JNF_CLASS_CACHE(jc_LWWindowPeer, "sun/lwawt/LWWindowPeer");
static JNF_MEMBER_CACHE(jf_Target, jc_LWWindowPeer, "target", "Ljava/awt/Component;");
if (peer == NULL) {
@@ -549,12 +572,27 @@
JNFDumpJavaStack(env);
return NULL;
}
- return JNFGetObjectField(env, peer, jf_Target);
+ jobject comp = JNFGetObjectField(env, peer, jf_Target);
+ (*env)->DeleteLocalRef(env, peer);
+ return comp;
+}
+
++ (AWTView *) awtView:(JNIEnv*)env ofAccessible:(jobject)jaccessible
+{
+ static JNF_STATIC_MEMBER_CACHE(jm_getAWTView, sjc_CAccessibility, "getAWTView", "(Ljavax/accessibility/Accessible;)J");
+
+ jlong jptr = JNFCallStaticLongMethod(env, jm_getAWTView, jaccessible);
+ if (jptr == 0) return nil;
+
+ return (AWTView *)jlong_to_ptr(jptr);
}
- (id)getAxData:(JNIEnv*)env
{
- return [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:[self awtComponent:env] withIndex:-1 withView:self withJavaRole:nil] autorelease];
+ jobject jcomponent = [self awtComponent:env];
+ id ax = [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:jcomponent withIndex:-1 withView:self withJavaRole:nil] autorelease];
+ (*env)->DeleteLocalRef(env, jcomponent);
+ return ax;
}
- (NSArray *)accessibilityAttributeNames
@@ -1299,7 +1337,7 @@
JNF_COCOA_ENTER(env);
NSRect rect = NSMakeRect(originX, originY, width, height);
- jobject cPlatformView = (*env)->NewGlobalRef(env, obj);
+ jobject cPlatformView = (*env)->NewWeakGlobalRef(env, obj);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,9 @@
{
self = [super init];
if (self) {
- fAccessibleAction = JNFNewGlobalRef(env, accessibleAction);
+ fAccessibleAction = JNFNewWeakGlobalRef(env, accessibleAction);
fIndex = index;
- fComponent = JNFNewGlobalRef(env, component);
+ fComponent = JNFNewWeakGlobalRef(env, component);
}
return self;
}
@@ -46,10 +46,10 @@
{
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
- JNFDeleteGlobalRef(env, fAccessibleAction);
+ JNFDeleteWeakGlobalRef(env, fAccessibleAction);
fAccessibleAction = NULL;
- JNFDeleteGlobalRef(env, fComponent);
+ JNFDeleteWeakGlobalRef(env, fComponent);
fComponent = NULL;
[super dealloc];
@@ -61,7 +61,18 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
- return JNFJavaToNSString(env, JNFCallStaticObjectMethod(env, jm_getAccessibleActionDescription, fAccessibleAction, fIndex, fComponent)); // AWT_THREADING Safe (AWTRunLoopMode)
+ jobject fCompLocal = (*env)->NewLocalRef(env, fComponent);
+ if ((*env)->IsSameObject(env, fCompLocal, NULL)) {
+ return @"unknown";
+ }
+ NSString *str = nil;
+ jobject jstr = JNFCallStaticObjectMethod(env, jm_getAccessibleActionDescription, fAccessibleAction, fIndex, fCompLocal);
+ if (jstr != NULL) {
+ NSString *str = JNFJavaToNSString(env, jstr); // AWT_THREADING Safe (AWTRunLoopMode)
+ (*env)->DeleteLocalRef(env, jstr);
+ }
+ (*env)->DeleteLocalRef(env, fCompLocal);
+ return str == nil ? @"unknown" : str;
}
- (void)perform
@@ -82,9 +93,9 @@
{
self = [super init];
if (self) {
- fTabGroup = JNFNewGlobalRef(env, tabGroup);
+ fTabGroup = JNFNewWeakGlobalRef(env, tabGroup);
fIndex = index;
- fComponent = JNFNewGlobalRef(env, component);
+ fComponent = JNFNewWeakGlobalRef(env, component);
}
return self;
}
@@ -93,10 +104,10 @@
{
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
- JNFDeleteGlobalRef(env, fTabGroup);
+ JNFDeleteWeakGlobalRef(env, fTabGroup);
fTabGroup = NULL;
- JNFDeleteGlobalRef(env, fComponent);
+ JNFDeleteWeakGlobalRef(env, fComponent);
fComponent = NULL;
[super dealloc];
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,9 @@
jobject axRole = JNFCallStaticObjectMethod(env, sjm_getAccessibleRole, axComponent, component); // AWT_THREADING Safe (AWTRunLoopMode)
if (axRole == NULL) return @"unknown";
- return JNFJavaToNSString(env, axRole);
+ NSString* str = JNFJavaToNSString(env, axRole);
+ (*env)->DeleteLocalRef(env, axRole);
+ return str;
}
jobject getAxSelection(JNIEnv *env, jobject axContext, jobject component)
@@ -126,21 +128,27 @@
{
static JNF_STATIC_MEMBER_CACHE(jm_VERTICAL, sjc_AccessibleState, "VERTICAL", "Ljavax/accessibility/AccessibleState;");
jobject axVertState = JNFGetStaticObjectField(env, jm_VERTICAL);
- return containsAxState(env, axContext, axVertState, component);
+ BOOL vertical = containsAxState(env, axContext, axVertState, component);
+ (*env)->DeleteLocalRef(env, axVertState);
+ return vertical;
}
BOOL isHorizontal(JNIEnv *env, jobject axContext, jobject component)
{
static JNF_STATIC_MEMBER_CACHE(jm_HORIZONTAL, sjc_AccessibleState, "HORIZONTAL", "Ljavax/accessibility/AccessibleState;");
jobject axHorizState = JNFGetStaticObjectField(env, jm_HORIZONTAL);
- return containsAxState(env, axContext, axHorizState, component);
+ BOOL horizontal = containsAxState(env, axContext, axHorizState, component);
+ (*env)->DeleteLocalRef(env, axHorizState);
+ return horizontal;
}
BOOL isShowing(JNIEnv *env, jobject axContext, jobject component)
{
static JNF_STATIC_MEMBER_CACHE(jm_SHOWING, sjc_AccessibleState, "SHOWING", "Ljavax/accessibility/AccessibleState;");
jobject axVisibleState = JNFGetStaticObjectField(env, jm_SHOWING);
- return containsAxState(env, axContext, axVisibleState, component);
+ BOOL showing = containsAxState(env, axContext, axVisibleState, component);
+ (*env)->DeleteLocalRef(env, axVisibleState);
+ return showing;
}
NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component)
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, 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
@@ -75,7 +75,6 @@
static NSMutableDictionary *sAttributeNamesForRoleCache = nil;
static NSObject *sAttributeNamesLOCK = nil;
-
@interface TabGroupAccessibility : JavaComponentAccessibility {
NSInteger _numTabs;
}
@@ -137,8 +136,11 @@
fView = [view retain];
fJavaRole = [javaRole retain];
- fAccessible = JNFNewGlobalRef(env, accessible);
- fComponent = JNFNewGlobalRef(env, [(AWTView *)fView awtComponent:env]);
+ fAccessible = (*env)->NewWeakGlobalRef(env, accessible);
+
+ jobject jcomponent = [(AWTView *)fView awtComponent:env];
+ fComponent = (*env)->NewWeakGlobalRef(env, jcomponent);
+ (*env)->DeleteLocalRef(env, jcomponent);
fIndex = index;
@@ -166,10 +168,10 @@
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
- JNFDeleteGlobalRef(env, fAccessible);
+ (*env)->DeleteWeakGlobalRef(env, fAccessible);
fAccessible = NULL;
- JNFDeleteGlobalRef(env, fComponent);
+ (*env)->DeleteWeakGlobalRef(env, fComponent);
fComponent = NULL;
[fParent release];
@@ -279,7 +281,7 @@
+ (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored
{
- jobjectArray jchildrenAndRoles = JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
+ jobjectArray jchildrenAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
if (jchildrenAndRoles == NULL) return nil;
jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles);
@@ -294,14 +296,21 @@
NSString *childJavaRole = nil;
if (jchildJavaRole != NULL) {
- childJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jchildJavaRole, sjf_key));
+ jobject jkey = JNFGetObjectField(env, jchildJavaRole, sjf_key);
+ childJavaRole = JNFJavaToNSString(env, jkey);
+ (*env)->DeleteLocalRef(env, jkey);
}
JavaComponentAccessibility *child = [self createWithParent:parent accessible:jchild role:childJavaRole index:childIndex withEnv:env withView:parent->fView];
+
+ (*env)->DeleteLocalRef(env, jchild);
+ (*env)->DeleteLocalRef(env, jchildJavaRole);
+
[children addObject:child];
childIndex++;
}
-
+ (*env)->DeleteLocalRef(env, jchildrenAndRoles);
+
return children;
}
@@ -310,7 +319,7 @@
jobject jcomponent = [(AWTView *)view awtComponent:env];
jint index = JNFCallStaticIntMethod(env, sjm_getAccessibleIndexInParent, jaccessible, jcomponent);
NSString *javaRole = getJavaRole(env, jaccessible, jcomponent);
-
+ (*env)->DeleteLocalRef(env, jcomponent);
return [self createWithAccessible:jaccessible role:javaRole index:index withEnv:env withView:view];
}
@@ -325,7 +334,10 @@
jobject jCAX = [JavaComponentAccessibility getCAccessible:jaccessible withEnv:env];
if (jCAX == NULL) return nil;
JavaComponentAccessibility *value = (JavaComponentAccessibility *) jlong_to_ptr(JNFGetLongField(env, jCAX, jf_ptr));
- if (value != nil) return [[value retain] autorelease];
+ if (value != nil) {
+ (*env)->DeleteLocalRef(env, jCAX);
+ return [[value retain] autorelease];
+ }
// otherwise, create a new instance
JavaComponentAccessibility *newChild = nil;
@@ -348,6 +360,7 @@
// must hard retain pointer poked into Java object
[newChild retain];
JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
+ (*env)->DeleteLocalRef(env, jCAX);
// return autoreleased instance
return [newChild autorelease];
@@ -380,7 +393,7 @@
// Get all the other accessibility attributes states we need in one swell foop.
// javaRole isn't pulled in because we need protected access to AccessibleRole.key
- jbooleanArray attributeStates = JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
+ jbooleanArray attributeStates = (jbooleanArray)JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
if (attributeStates == NULL) return nil;
jboolean *attributeStatesArray = (*env)->GetBooleanArrayElements(env, attributeStates, 0);
if (attributeStatesArray == NULL) {
@@ -475,6 +488,7 @@
JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:0 withComponent:fComponent];
[fActions setObject:action forKey:[self isMenu] ? NSAccessibilityPickAction : NSAccessibilityPressAction];
[action release];
+ (*env)->DeleteLocalRef(env, axAction);
}
}
@@ -485,7 +499,9 @@
- (id)parent
{
+ static JNF_CLASS_CACHE(sjc_Window, "java/awt/Window");
static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleParent, sjc_CAccessibility, "getAccessibleParent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;");
+ static JNF_STATIC_MEMBER_CACHE(sjm_getSwingAccessible, sjc_CAccessible, "getSwingAccessible", "(Ljavax/accessibility/Accessible;)Ljavax/accessibility/Accessible;");
if(fParent == nil) {
JNIEnv* env = [ThreadUtilities getJNIEnv];
@@ -495,10 +511,21 @@
if (jparent == NULL) {
fParent = fView;
} else {
- fParent = [JavaComponentAccessibility createWithAccessible:jparent withEnv:env withView:fView];
+ AWTView *view = fView;
+ jobject jax = JNFCallStaticObjectMethod(env, sjm_getSwingAccessible, fAccessible);
+
+ if (JNFIsInstanceOf(env, jax, &sjc_Window)) {
+ // In this case jparent is an owner toplevel and we should retrieve its own view
+ view = [AWTView awtView:env ofAccessible:jparent];
+ }
+ if (view != nil) {
+ fParent = [JavaComponentAccessibility createWithAccessible:jparent withEnv:env withView:view];
+ }
if (fParent == nil) {
fParent = fView;
}
+ (*env)->DeleteLocalRef(env, jparent);
+ (*env)->DeleteLocalRef(env, jax );
}
[fParent retain];
}
@@ -546,7 +573,10 @@
return NO;
}
- return isShowing(env, [self axContextWithEnv:env], fComponent);
+ jobject axContext = [self axContextWithEnv:env];
+ BOOL showing = isShowing(env, axContext, fComponent);
+ (*env)->DeleteLocalRef(env, axContext);
+ return showing;
}
// the array of names for each role is cached in the sAttributeNamesForRoleCache
@@ -723,7 +753,12 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleDescription, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return JNFJavaToNSString(env, val);
+ if (val == NULL) {
+ return @"unknown";
+ }
+ NSString* str = JNFJavaToNSString(env, val);
+ (*env)->DeleteLocalRef(env, val);
+ return str;
}
- (BOOL)accessibilityIsHelpAttributeSettable
@@ -739,7 +774,12 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject axValue = JNFCallStaticObjectMethod(env, jm_getMaximumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return JNFJavaToNSNumber(env, axValue);
+ if (axValue == NULL) {
+ return [NSNumber numberWithInt:0];
+ }
+ NSNumber* num = JNFJavaToNSNumber(env, axValue);
+ (*env)->DeleteLocalRef(env, axValue);
+ return num;
}
- (BOOL)accessibilityIsMaxValueAttributeSettable
@@ -755,7 +795,12 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject axValue = JNFCallStaticObjectMethod(env, jm_getMinimumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return JNFJavaToNSNumber(env, axValue);
+ if (axValue == NULL) {
+ return [NSNumber numberWithInt:0];
+ }
+ NSNumber* num = JNFJavaToNSNumber(env, axValue);
+ (*env)->DeleteLocalRef(env, axValue);
+ return num;
}
- (BOOL)accessibilityIsMinValueAttributeSettable
@@ -770,13 +815,16 @@
// cmcnote - should batch these two calls into one that returns an array of two bools, one for vertical and one for horiz
if (isVertical(env, axContext, fComponent)) {
+ (*env)->DeleteLocalRef(env, axContext);
return NSAccessibilityVerticalOrientationValue;
}
if (isHorizontal(env, axContext, fComponent)) {
+ (*env)->DeleteLocalRef(env, axContext);
return NSAccessibilityHorizontalOrientationValue;
}
+ (*env)->DeleteLocalRef(env, axContext);
return nil;
}
@@ -808,6 +856,7 @@
// Get the java screen coords, and make a NSPoint of the bottom left of the AxComponent.
NSSize size = getAxComponentSize(env, axComponent, fComponent);
NSPoint point = getAxComponentLocationOnScreen(env, axComponent, fComponent);
+ (*env)->DeleteLocalRef(env, axComponent);
point.y += size.height;
@@ -857,8 +906,9 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject axRole = JNFCallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent);
- if(axRole != NULL) {
+ if (axRole != NULL) {
value = JNFJavaToNSString(env, axRole);
+ (*env)->DeleteLocalRef(env, axRole);
} else {
value = @"unknown";
}
@@ -893,7 +943,9 @@
- (NSValue *)accessibilitySizeAttribute {
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)];
+ NSValue* size = [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)];
+ (*env)->DeleteLocalRef(env, axComponent);
+ return size;
}
- (BOOL)accessibilityIsSizeAttributeSettable
@@ -952,7 +1004,12 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return JNFJavaToNSString(env, val);
+ if (val == NULL) {
+ return @"unknown";
+ }
+ NSString* str = JNFJavaToNSString(env, val);
+ (*env)->DeleteLocalRef(env, val);
+ return str;
}
- (BOOL)accessibilityIsTitleAttributeSettable
@@ -984,8 +1041,20 @@
// a text value is taken care of in JavaTextAccessibility
// cmcnote should coalesce these calls into one java call
+ NSNumber *num = nil;
jobject axValue = JNFCallStaticObjectMethod(env, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return JNFJavaToNSNumber(env, JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent)); // AWT_THREADING Safe (AWTRunLoop)
+ if (axValue != NULL) {
+ jobject str = JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent);
+ if (str != NULL) {
+ num = JNFJavaToNSNumber(env, str); // AWT_THREADING Safe (AWTRunLoop)
+ (*env)->DeleteLocalRef(env, str);
+ }
+ (*env)->DeleteLocalRef(env, axValue);
+ }
+ if (num == nil) {
+ num = [NSNumber numberWithInt:0];
+ }
+ return num;
}
- (BOOL)accessibilityIsValueAttributeSettable
@@ -1084,7 +1153,10 @@
id value = nil;
if (JNFIsInstanceOf(env, jparent, &jc_Container)) {
jobject jaccessible = JNFCallStaticObjectMethod(env, jm_accessibilityHitTest, jparent, (jfloat)point.x, (jfloat)point.y); // AWT_THREADING Safe (AWTRunLoop)
- value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView];
+ if (jaccessible != NULL) {
+ value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView];
+ (*env)->DeleteLocalRef(env, jaccessible);
+ }
}
if (value == nil) {
@@ -1116,6 +1188,7 @@
if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
}
+ (*env)->DeleteLocalRef(env, focused);
}
if (value == nil) {
@@ -1222,38 +1295,46 @@
for (i = 0; i < _numTabs; i++) {
aTab = (JavaComponentAccessibility *)[tabs objectAtIndex:i];
if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) {
+ (*env)->DeleteLocalRef(env, selAccessible);
return aTab;
}
}
-
+ (*env)->DeleteLocalRef(env, selAccessible);
return nil;
}
- (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
{
- jobjectArray jtabsAndRoles = JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
+ jobjectArray jtabsAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
if(jtabsAndRoles == NULL) return nil;
jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles);
- if (arrayLen == 0) return nil;
-
+ if (arrayLen == 0) {
+ (*env)->DeleteLocalRef(env, jtabsAndRoles);
+ return nil;
+ }
NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)];
// all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs
jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1.
- if (jtabJavaRole == NULL) return nil;
-
- NSString *tabJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jtabJavaRole, sjf_key));
+ if (jtabJavaRole == NULL) {
+ (*env)->DeleteLocalRef(env, jtabsAndRoles);
+ return nil;
+ }
+ jobject jkey = JNFGetObjectField(env, jtabJavaRole, sjf_key);
+ NSString *tabJavaRole = JNFJavaToNSString(env, jkey);
+ (*env)->DeleteLocalRef(env, jkey);
NSInteger i;
NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly
for(i = 0; i < arrayLen; i+=2) {
jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i);
JavaComponentAccessibility *tab = [[[TabGroupControlAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease];
+ (*env)->DeleteLocalRef(env, jtab);
[tabs addObject:tab];
tabIndex++;
}
-
+ (*env)->DeleteLocalRef(env, jtabsAndRoles);
return tabs;
}
@@ -1272,7 +1353,9 @@
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject axContext = [self axContextWithEnv:env];
- return [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
+ id tabs = [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
+ (*env)->DeleteLocalRef(env, axContext);
+ return tabs;
}
- (BOOL)accessibilityIsTabsAttributeSettable
@@ -1292,7 +1375,9 @@
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject axContext = [self axContextWithEnv:env];
- return [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
+ NSArray* cont = [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
+ (*env)->DeleteLocalRef(env, axContext);
+ return cont;
}
- (BOOL)accessibilityIsContentsAttributeSettable
@@ -1305,7 +1390,9 @@
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject axContext = [self axContextWithEnv:env];
- return [self currentTabWithEnv:env withAxContext:axContext];
+ id val = [self currentTabWithEnv:env withAxContext:axContext];
+ (*env)->DeleteLocalRef(env, axContext);
+ return val;
}
- (BOOL)accessibilityIsValueAttributeSettable
@@ -1322,6 +1409,7 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject axContext = [self axContextWithEnv:env];
setAxContextSelection(env, axContext, fIndex, fComponent);
+ (*env)->DeleteLocalRef(env, axContext);
}
- (NSArray *)accessibilityChildrenAttribute
@@ -1357,6 +1445,7 @@
result = children;
}
}
+ (*env)->DeleteLocalRef(env, axContext);
} else {
result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
}
@@ -1375,7 +1464,7 @@
self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole];
if (self) {
if (tabGroup != NULL) {
- fTabGroupAxContext = JNFNewGlobalRef(env, tabGroup);
+ fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroup);
} else {
fTabGroupAxContext = NULL;
}
@@ -1388,7 +1477,7 @@
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
if (fTabGroupAxContext != NULL) {
- JNFDeleteGlobalRef(env, fTabGroupAxContext);
+ JNFDeleteWeakGlobalRef(env, fTabGroupAxContext);
fTabGroupAxContext = NULL;
}
@@ -1399,9 +1488,14 @@
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject axContext = [self axContextWithEnv:env];
+ jobject selAccessible = getAxContextSelection(env, [self tabGroup], fIndex, fComponent);
// Returns the current selection of the page tab list
- return [NSNumber numberWithBool:ObjectEquals(env, axContext, getAxContextSelection(env, [self tabGroup], fIndex, fComponent), fComponent)];
+ id val = [NSNumber numberWithBool:ObjectEquals(env, axContext, selAccessible, fComponent)];
+
+ (*env)->DeleteLocalRef(env, selAccessible);
+ (*env)->DeleteLocalRef(env, axContext);
+ return val;
}
- (void)getActionsWithEnv:(JNIEnv *)env
@@ -1416,7 +1510,8 @@
if (fTabGroupAxContext == NULL) {
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject tabGroupAxContext = [(JavaComponentAccessibility *)[self parent] axContextWithEnv:env];
- fTabGroupAxContext = JNFNewGlobalRef(env, tabGroupAxContext);
+ fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroupAxContext);
+ (*env)->DeleteLocalRef(env, tabGroupAxContext);
}
return fTabGroupAxContext;
}
@@ -1451,8 +1546,10 @@
if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
jobject elementAxContext = [aElement axContextWithEnv:env];
if (isHorizontal(env, elementAxContext, fComponent)) {
+ (*env)->DeleteLocalRef(env, elementAxContext);
return aElement;
}
+ (*env)->DeleteLocalRef(env, elementAxContext);
}
}
@@ -1478,8 +1575,10 @@
if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
jobject elementAxContext = [aElement axContextWithEnv:env];
if (isVertical(env, elementAxContext, fComponent)) {
+ (*env)->DeleteLocalRef(env, elementAxContext);
return aElement;
}
+ (*env)->DeleteLocalRef(env, elementAxContext);
}
}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,7 +112,9 @@
// if it's static text, the AppKit AXValue is the java accessibleName
jobject axName = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
if (axName != NULL) {
- return JNFJavaToNSString(env, axName);
+ NSString* str = JNFJavaToNSString(env, axName);
+ (*env)->DeleteLocalRef(env, axName);
+ return str;
}
// value is still nil if no accessibleName for static text. Below, try to get the accessibleText.
}
@@ -120,12 +122,18 @@
// cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923
jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
if (axText == NULL) return nil;
-
+ (*env)->DeleteLocalRef(env, axText);
+
jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
if (axEditableText == NULL) return nil;
static JNF_STATIC_MEMBER_CACHE(jm_getTextRange, sjc_CAccessibleText, "getTextRange", "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;");
- NSString *string = JNFJavaToNSString(env, JNFCallStaticObjectMethod(env, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent)); // AWT_THREADING Safe (AWTRunLoop)
+ jobject jrange = JNFCallStaticObjectMethod(env, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
+ NSString *string = JNFJavaToNSString(env, jrange); // AWT_THREADING Safe (AWTRunLoop)
+
+ (*env)->DeleteLocalRef(env, jrange);
+ (*env)->DeleteLocalRef(env, axEditableText);
+
if (string == nil) string = @"";
return string;
}
@@ -139,6 +147,7 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
if (axEditableText == NULL) return NO;
+ (*env)->DeleteLocalRef(env, axEditableText);
return YES;
}
@@ -157,7 +166,9 @@
static JNF_STATIC_MEMBER_CACHE(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
jobject axText = JNFCallStaticObjectMethod(env, jm_getSelectedText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
if (axText == NULL) return @"";
- return JNFJavaToNSString(env, axText);
+ NSString* str = JNFJavaToNSString(env, axText);
+ (*env)->DeleteLocalRef(env, axText);
+ return str;
}
- (BOOL)accessibilityIsSelectedTextAttributeSettable
@@ -220,7 +231,9 @@
// also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
- return [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)];
+ NSNumber* num = [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)];
+ (*env)->DeleteLocalRef(env, axText);
+ return num;
}
- (BOOL)accessibilityIsNumberOfCharactersAttributeSettable
@@ -285,7 +298,7 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_STATIC_MEMBER_CACHE(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D");
- jdoubleArray axBounds = JNFCallStaticObjectMethod(env, jm_getBoundsForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
+ jdoubleArray axBounds = (jdoubleArray)JNFCallStaticObjectMethod(env, jm_getBoundsForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
if (axBounds == NULL) return nil;
// We cheat because we know that the array is 4 elements long (x, y, width, height)
@@ -324,7 +337,7 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_STATIC_MEMBER_CACHE(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I");
- jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop)
+ jintArray axTextRange = (jintArray)JNFCallStaticObjectMethod(env, jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop)
if (axTextRange == NULL) return nil;
return javaIntArrayToNSRangeValue(env,axTextRange);
@@ -350,10 +363,12 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_STATIC_MEMBER_CACHE(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;");
- jstring jstringForRange = JNFCallStaticObjectMethod(env, jm_getStringForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
+ jstring jstringForRange = (jstring)JNFCallStaticObjectMethod(env, jm_getStringForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
if (jstringForRange == NULL) return @"";
- return JNFJavaToNSString(env, jstringForRange);
+ NSString* str = JNFJavaToNSString(env, jstringForRange);
+ (*env)->DeleteLocalRef(env, jstringForRange);
+ return str;
}
//
@@ -406,7 +421,7 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_STATIC_MEMBER_CACHE(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I");
- jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getRangeForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop)
+ jintArray axTextRange = (jintArray)JNFCallStaticObjectMethod(env, jm_getRangeForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop)
if (axTextRange == NULL) return nil;
return javaIntArrayToNSRangeValue(env, axTextRange);
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -31,7 +31,7 @@
@interface CGLLayer : CAOpenGLLayer
{
@private
- JNFJObjectWrapper *javaLayer;
+ JNFWeakJObjectWrapper *javaLayer;
// intermediate buffer, used the RQ lock to synchronize
GLuint textureID;
@@ -45,7 +45,7 @@
#endif /* REMOTELAYER */
}
-@property (nonatomic, retain) JNFJObjectWrapper *javaLayer;
+@property (nonatomic, retain) JNFWeakJObjectWrapper *javaLayer;
@property (readwrite, assign) GLuint textureID;
@property (readwrite, assign) GLenum target;
@property (readwrite, assign) float textureWidth;
@@ -57,7 +57,7 @@
@property (nonatomic, retain) NSObject<JRSRemoteLayer> *jrsRemoteLayer;
#endif
-- (id) initWithJavaLayer:(JNFJObjectWrapper *)javaLayer;
+- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)javaLayer;
- (void) blitTexture;
@end
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, 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
@@ -46,7 +46,7 @@
@synthesize jrsRemoteLayer;
#endif
-- (id) initWithJavaLayer:(JNFJObjectWrapper *)layer;
+- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer;
{
AWT_ASSERT_APPKIT_THREAD;
// Initialize ourselves
@@ -133,6 +133,15 @@
{
AWT_ASSERT_APPKIT_THREAD;
+ JNIEnv *env = [ThreadUtilities getJNIEnv];
+ static JNF_CLASS_CACHE(jc_JavaLayer, "sun/java2d/opengl/CGLLayer");
+ static JNF_MEMBER_CACHE(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V");
+
+ jobject javaLayerLocalRef = [self.javaLayer jObjectWithEnv:env];
+ if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) {
+ return;
+ }
+
// Set the current context to the one given to us.
CGLSetCurrentContext(glContext);
@@ -141,12 +150,7 @@
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, textureWidth, textureHeight);
-
- JNIEnv *env = [ThreadUtilities getJNIEnv];
- static JNF_CLASS_CACHE(jc_JavaLayer, "sun/java2d/opengl/CGLLayer");
- static JNF_MEMBER_CACHE(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V");
- jobject javaLayerLocalRef = [self.javaLayer jObjectWithEnv:env];
JNFCallVoidMethod(env, javaLayerLocalRef, jm_drawInCGLContext);
(*env)->DeleteLocalRef(env, javaLayerLocalRef);
@@ -171,7 +175,7 @@
JNF_COCOA_ENTER(env);
- JNFJObjectWrapper *javaLayer = [JNFJObjectWrapper wrapperWithJObject:obj withEnv:env];
+ JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
AWT_ASSERT_APPKIT_THREAD;
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java Fri May 06 06:23:30 2016 -0700
@@ -42,7 +42,7 @@
* <new class="java.lang.Long">
* <string>10</string>
* </new></pre>
- * is equivalent to {@code new Long("10")} in Java code.
+ * is equivalent to {@code Long.valueOf("10")} in Java code.
* <p>The following attributes are supported:
* <dl>
* <dt>class
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java Fri May 06 06:23:30 2016 -0700
@@ -128,7 +128,7 @@
addChildNode(root, "BMPVersion", bmpVersion);
addChildNode(root, "Width", width);
addChildNode(root, "Height", height);
- addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel));
+ addChildNode(root, "BitsPerPixel", Short.valueOf(bitsPerPixel));
addChildNode(root, "Compression", compression);
addChildNode(root, "ImageSize", imageSize);
@@ -172,12 +172,12 @@
red = palette[j++] & 0xff;
green = palette[j++] & 0xff;
blue = palette[j++] & 0xff;
- addChildNode(entry, "Red", new Byte((byte)red));
- addChildNode(entry, "Green", new Byte((byte)green));
- addChildNode(entry, "Blue", new Byte((byte)blue));
+ addChildNode(entry, "Red", Byte.valueOf((byte)red));
+ addChildNode(entry, "Green", Byte.valueOf((byte)green));
+ addChildNode(entry, "Blue", Byte.valueOf((byte)blue));
if (numComps == 4)
addChildNode(entry, "Alpha",
- new Byte((byte)(palette[j++] & 0xff)));
+ Byte.valueOf((byte)(palette[j++] & 0xff)));
}
}
@@ -284,9 +284,9 @@
private void addXYZPoints(IIOMetadataNode root, String name, double x, double y, double z) {
IIOMetadataNode node = addChildNode(root, name, null);
- addChildNode(node, "X", new Double(x));
- addChildNode(node, "Y", new Double(y));
- addChildNode(node, "Z", new Double(z));
+ addChildNode(node, "X", Double.valueOf(x));
+ addChildNode(node, "Y", Double.valueOf(y));
+ addChildNode(node, "Z", Double.valueOf(z));
}
private IIOMetadataNode addChildNode(IIOMetadataNode root,
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, 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
@@ -158,8 +158,8 @@
int widgetType, int state, int shadowType, String detail,
int x, int y, int width, int height, int synthState, int dir);
private native void native_paint_slider(
- int widgetType, int state, int shadowType, String detail,
- int x, int y, int width, int height, int orientation);
+ int widgetType, int state, int shadowType, String detail, int x,
+ int y, int width, int height, int orientation, boolean hasFocus);
private native void native_paint_vline(
int widgetType, int state, String detail,
int x, int y, int width, int height);
@@ -491,6 +491,14 @@
int gtkState =
GTKLookAndFeel.synthStateToGTKStateType(state).ordinal();
int synthState = context.getComponentState();
+ Container parent = context.getComponent().getParent();
+ if(GTKLookAndFeel.is3()) {
+ if (parent != null && parent.getParent() instanceof JComboBox) {
+ if (parent.getParent().hasFocus()) {
+ synthState |= SynthConstants.FOCUSED;
+ }
+ }
+ }
int dir = getTextDirection(context);
int widget = getWidgetType(context.getComponent(), id).ordinal();
native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail,
@@ -498,13 +506,13 @@
}
public void paintSlider(Graphics g, SynthContext context,
- Region id, int state, ShadowType shadowType, String detail,
- int x, int y, int w, int h, Orientation orientation) {
+ Region id, int state, ShadowType shadowType, String detail, int x,
+ int y, int w, int h, Orientation orientation, boolean hasFocus) {
state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal();
int widget = getWidgetType(context.getComponent(), id).ordinal();
native_paint_slider(widget, state, shadowType.ordinal(), detail,
- x - x0, y - y0, w, h, orientation.ordinal());
+ x - x0, y - y0, w, h, orientation.ordinal(), hasFocus);
}
public void paintVline(Graphics g, SynthContext context,
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, 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
@@ -54,7 +54,8 @@
*/
@SuppressWarnings("serial") // Superclass not serializable
public class GTKLookAndFeel extends SynthLookAndFeel {
- private static final boolean IS_22;
+ private static boolean IS_22;
+ private static boolean IS_3;
/**
* Whether or not text is drawn antialiased. This keys off the
@@ -107,17 +108,6 @@
private static String gtkThemeName = "Default";
static {
- // Backup for specifying the version, this isn't currently documented.
- // If you pass in anything but 2.2 you got the 2.0 colors/look.
- String version = AccessController.doPrivileged(
- new GetPropertyAction("swing.gtk.version"));
- if (version != null) {
- IS_22 = version.equals("2.2");
- }
- else {
- IS_22 = true;
- }
-
String language = Locale.getDefault().getLanguage();
boolean cjkLocale =
(Locale.CHINESE.getLanguage().equals(language) ||
@@ -158,6 +148,10 @@
return IS_22;
}
+ static boolean is3() {
+ return IS_3;
+ }
+
/**
* Maps a swing constant to a GTK constant.
*/
@@ -385,7 +379,7 @@
}
Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0);
- Double defaultCaretAspectRatio = new Double(0.025);
+ Double defaultCaretAspectRatio = Double.valueOf(0.025);
Color caretColor = table.getColor("caretColor");
Color controlText = table.getColor("controlText");
@@ -1460,6 +1454,19 @@
throw new InternalError("Unable to load native GTK libraries");
}
+ if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) {
+ String version = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.gtk.version"));
+ if (version != null) {
+ IS_22 = version.equals("2.2");
+ } else {
+ IS_22 = true;
+ }
+ } else if (UNIXToolkit.getGtkVersion() ==
+ UNIXToolkit.GtkVersions.GTK3) {
+ IS_3 = true;
+ }
+
super.initialize();
inInitialize = true;
loadStyles();
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, 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
@@ -576,12 +576,11 @@
ShadowType.OUT, "menu", x, y, w, h);
GTKStyle style = (GTKStyle)context.getStyle();
- int xThickness = style.getXThickness();
- int yThickness = style.getYThickness();
+ Insets insets = style.getInsets(context, null);
ENGINE.paintBackground(g, context, id, gtkState,
- style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
- x + xThickness, y + yThickness,
- w - xThickness - xThickness, h - yThickness - yThickness);
+ style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
+ x + insets.left, y + insets.top, w - insets.left - insets.right,
+ h - insets.top - insets.bottom);
ENGINE.finishPainting();
}
}
@@ -640,6 +639,34 @@
int state = context.getComponentState();
JComponent c = context.getComponent();
+ GTKStyle style = (GTKStyle) context.getStyle();
+ String detail;
+ // wide-separators are painted using box not line
+ if (style.getClassSpecificBoolValue(context,
+ "wide-separators", false)) {
+ Insets insets = c.getInsets();
+ x += insets.left;
+ y += insets.top;
+ if (orientation == JSeparator.HORIZONTAL) {
+ w -= (insets.left + insets.right);
+ detail = "hseparator";
+ } else {
+ h -= (insets.top + insets.bottom);
+ detail = "vseparator";
+ }
+ synchronized (UNIXToolkit.GTK_LOCK) {
+ if (! ENGINE.paintCachedImage(g, x, y, w, h, id, state,
+ detail, orientation)) {
+ ENGINE.startPainting(g, x, y, w, h, id, state,
+ detail, orientation);
+ ENGINE.paintBox(g, context, id, state,
+ ShadowType.ETCHED_OUT, detail, x, y, w, h);
+ ENGINE.finishPainting();
+ }
+ }
+ return;
+ }
+
/*
* Note: In theory, the style's x/y thickness values would determine
* the width of the separator content. In practice, however, some
@@ -650,7 +677,6 @@
* the w/h values below too much, so that the full thickness of the
* rendered line will be captured by our image caching code.
*/
- String detail;
if (c instanceof JToolBar.Separator) {
/*
* GTK renders toolbar separators differently in that an
@@ -678,7 +704,6 @@
float pct = 0.2f;
JToolBar.Separator sep = (JToolBar.Separator)c;
Dimension size = sep.getSeparatorSize();
- GTKStyle style = (GTKStyle)context.getStyle();
if (orientation == JSeparator.HORIZONTAL) {
x += (int)(w * pct);
w -= (int)(w * pct * 2);
@@ -743,6 +768,15 @@
// The ubuntulooks engine paints slider troughs differently depending
// on the current slider value and its component orientation.
JSlider slider = (JSlider)context.getComponent();
+ if (GTKLookAndFeel.is3()) {
+ if (slider.getOrientation() == JSlider.VERTICAL) {
+ y += 1;
+ h -= 2;
+ } else {
+ x += 1;
+ w -= 2;
+ }
+ }
double value = slider.getValue();
double min = slider.getMinimum();
double max = slider.getMaximum();
@@ -776,15 +810,19 @@
Region id = context.getRegion();
int gtkState = GTKLookAndFeel.synthStateToGTKState(
id, context.getComponentState());
+ boolean hasFocus = GTKLookAndFeel.is3() &&
+ ((context.getComponentState() & SynthConstants.FOCUSED) != 0);
synchronized (UNIXToolkit.GTK_LOCK) {
- if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir)) {
+ if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir,
+ hasFocus)) {
Orientation orientation = (dir == JSlider.HORIZONTAL ?
Orientation.HORIZONTAL : Orientation.VERTICAL);
String detail = (dir == JSlider.HORIZONTAL ?
"hscale" : "vscale");
ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir);
ENGINE.paintSlider(g, context, id, gtkState,
- ShadowType.OUT, detail, x, y, w, h, orientation);
+ ShadowType.OUT, detail, x, y, w, h, orientation,
+ hasFocus);
ENGINE.finishPainting();
}
}
@@ -963,15 +1001,21 @@
int yThickness = style.getYThickness();
ENGINE.startPainting(g, x, y, w, h, id, state);
+ if (GTKLookAndFeel.is3()) {
+ ENGINE.paintBackground(g, context, id, gtkState, null,
+ x, y, w, h);
+ }
ENGINE.paintShadow(g, context, id, gtkState,
ShadowType.IN, "entry", x, y, w, h);
- ENGINE.paintFlatBox(g, context, id,
- gtkState, ShadowType.NONE, "entry_bg",
- x + xThickness,
- y + yThickness,
- w - (2 * xThickness),
- h - (2 * yThickness),
- ColorType.TEXT_BACKGROUND);
+ if (!GTKLookAndFeel.is3()) {
+ ENGINE.paintFlatBox(g, context, id,
+ gtkState, ShadowType.NONE, "entry_bg",
+ x + xThickness,
+ y + yThickness,
+ w - (2 * xThickness),
+ h - (2 * yThickness),
+ ColorType.TEXT_BACKGROUND);
+ }
if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) {
if (!interiorFocus) {
@@ -982,14 +1026,14 @@
} else {
if (containerParent instanceof JComboBox) {
x += (focusSize + 2);
- y += (focusSize + 1);
- w -= (2 * focusSize + 1);
- h -= (2 * focusSize + 2);
+ y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1);
+ w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1);
+ h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2);
} else {
- x += focusSize;
- y += focusSize;
- w -= 2 * focusSize;
- h -= 2 * focusSize;
+ x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0);
+ y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 );
+ w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0);
+ h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0);
}
}
ENGINE.paintFocus(g, context, id, gtkState,
@@ -1138,8 +1182,8 @@
Orientation orientation = (dir == JScrollBar.HORIZONTAL ?
Orientation.HORIZONTAL : Orientation.VERTICAL);
ENGINE.setRangeValue(context, id, value, min, max, visible);
- ENGINE.paintSlider(g, context, id, gtkState,
- ShadowType.OUT, "slider", x, y, w, h, orientation);
+ ENGINE.paintSlider(g, context, id, gtkState, ShadowType.OUT,
+ "slider", x, y, w, h, orientation, false);
ENGINE.finishPainting();
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, 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
@@ -715,29 +715,33 @@
if (region == Region.COMBO_BOX ||
region == Region.DESKTOP_PANE ||
region == Region.DESKTOP_ICON ||
- region == Region.EDITOR_PANE ||
- region == Region.FORMATTED_TEXT_FIELD ||
region == Region.INTERNAL_FRAME ||
region == Region.LIST ||
region == Region.MENU_BAR ||
region == Region.PANEL ||
- region == Region.PASSWORD_FIELD ||
region == Region.POPUP_MENU ||
region == Region.PROGRESS_BAR ||
region == Region.ROOT_PANE ||
region == Region.SCROLL_PANE ||
- region == Region.SPINNER ||
region == Region.SPLIT_PANE_DIVIDER ||
region == Region.TABLE ||
region == Region.TEXT_AREA ||
- region == Region.TEXT_FIELD ||
- region == Region.TEXT_PANE ||
region == Region.TOOL_BAR_DRAG_WINDOW ||
region == Region.TOOL_TIP ||
region == Region.TREE ||
region == Region.VIEWPORT) {
return true;
}
+ if (!GTKLookAndFeel.is3()) {
+ if (region == Region.EDITOR_PANE ||
+ region == Region.FORMATTED_TEXT_FIELD ||
+ region == Region.PASSWORD_FIELD ||
+ region == Region.SPINNER ||
+ region == Region.TEXT_FIELD ||
+ region == Region.TEXT_PANE) {
+ return true;
+ }
+ }
Component c = context.getComponent();
String name = c.getName();
if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") {
@@ -776,6 +780,15 @@
}
else if (key == "Separator.thickness") {
JSeparator sep = (JSeparator)context.getComponent();
+ if (getClassSpecificBoolValue(context, "wide-separators", false)) {
+ if (sep.getOrientation() == JSeparator.HORIZONTAL) {
+ return getClassSpecificIntValue(context,
+ "separator-height", 0);
+ } else {
+ return getClassSpecificIntValue(context,
+ "separator-width", 0);
+ }
+ }
if (sep.getOrientation() == JSeparator.HORIZONTAL) {
return getYThickness();
} else {
@@ -783,6 +796,12 @@
}
}
else if (key == "ToolBar.separatorSize") {
+ if (getClassSpecificBoolValue(context, "wide-separators", false)) {
+ return new DimensionUIResource(
+ getClassSpecificIntValue(context, "separator-width", 2),
+ getClassSpecificIntValue(context, "separator-height", 2)
+ );
+ }
int size = getClassSpecificIntValue(WidgetType.TOOL_BAR,
"space-size", 12);
return new DimensionUIResource(size, size);
@@ -833,6 +852,8 @@
int focusPad =
getClassSpecificIntValue(context, "focus-padding", 1);
return indicatorSpacing + focusSize + focusPad;
+ } else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) {
+ return true;
}
// Is it a stock icon ?
@@ -1112,6 +1133,7 @@
static {
CLASS_SPECIFIC_MAP = new HashMap<String,String>();
CLASS_SPECIFIC_MAP.put("Slider.thumbHeight", "slider-width");
+ CLASS_SPECIFIC_MAP.put("Slider.thumbWidth", "slider-length");
CLASS_SPECIFIC_MAP.put("Slider.trackBorder", "trough-border");
CLASS_SPECIFIC_MAP.put("SplitPane.size", "handle-size");
CLASS_SPECIFIC_MAP.put("Tree.expanderSize", "expander-size");
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java Fri May 06 06:23:30 2016 -0700
@@ -185,7 +185,7 @@
getIntAttr(child, "bottom", 0),
getIntAttr(child, "right", 0));
} else if ("aspect_ratio".equals(name)) {
- value = new Float(getFloatAttr(child, "value", 1.0F));
+ value = Float.valueOf(getFloatAttr(child, "value", 1.0F));
} else {
logError(themeName, "Unknown Metacity frame geometry value type: "+name);
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,6 @@
-import sun.swing.UIClientPropertyKey;
import com.sun.java.swing.plaf.windows.TMSchema.State;
import static com.sun.java.swing.plaf.windows.TMSchema.State.*;
import com.sun.java.swing.plaf.windows.TMSchema.Part;
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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,7 +68,6 @@
import sun.awt.ConstrainableGraphics;
import sun.awt.SubRegionShowable;
import sun.awt.SunToolkit;
-import sun.awt.CausedFocusEvent;
import sun.awt.EmbeddedFrame;
import sun.awt.dnd.SunDropTargetEvent;
import sun.awt.im.CompositionArea;
@@ -878,7 +877,7 @@
{
comp.setGraphicsConfiguration(gc);
}
- public boolean requestFocus(Component comp, CausedFocusEvent.Cause cause) {
+ public boolean requestFocus(Component comp, FocusEvent.Cause cause) {
return comp.requestFocus(cause);
}
public boolean canBeFocusOwner(Component comp) {
@@ -7538,7 +7537,7 @@
requestFocusHelper(false, true);
}
- boolean requestFocus(CausedFocusEvent.Cause cause) {
+ boolean requestFocus(FocusEvent.Cause cause) {
return requestFocusHelper(false, true, cause);
}
@@ -7605,7 +7604,7 @@
return requestFocusHelper(temporary, true);
}
- boolean requestFocus(boolean temporary, CausedFocusEvent.Cause cause) {
+ boolean requestFocus(boolean temporary, FocusEvent.Cause cause) {
return requestFocusHelper(temporary, true, cause);
}
/**
@@ -7656,7 +7655,7 @@
return requestFocusHelper(false, false);
}
- boolean requestFocusInWindow(CausedFocusEvent.Cause cause) {
+ boolean requestFocusInWindow(FocusEvent.Cause cause) {
return requestFocusHelper(false, false, cause);
}
@@ -7721,18 +7720,18 @@
return requestFocusHelper(temporary, false);
}
- boolean requestFocusInWindow(boolean temporary, CausedFocusEvent.Cause cause) {
+ boolean requestFocusInWindow(boolean temporary, FocusEvent.Cause cause) {
return requestFocusHelper(temporary, false, cause);
}
final boolean requestFocusHelper(boolean temporary,
boolean focusedWindowChangeAllowed) {
- return requestFocusHelper(temporary, focusedWindowChangeAllowed, CausedFocusEvent.Cause.UNKNOWN);
+ return requestFocusHelper(temporary, focusedWindowChangeAllowed, FocusEvent.Cause.UNKNOWN);
}
final boolean requestFocusHelper(boolean temporary,
boolean focusedWindowChangeAllowed,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
// 1) Check if the event being dispatched is a system-generated mouse event.
AWTEvent currentEvent = EventQueue.getCurrentEvent();
@@ -7820,7 +7819,7 @@
private boolean isRequestFocusAccepted(boolean temporary,
boolean focusedWindowChangeAllowed,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
if (!isFocusable() || !isVisible()) {
if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
@@ -7867,7 +7866,7 @@
return true;
}
- if (CausedFocusEvent.Cause.ACTIVATION == cause) {
+ if (FocusEvent.Cause.ACTIVATION == cause) {
// we shouldn't call RequestFocusController in case we are
// in activation. We do request focus on component which
// has got temporary focus lost and then on component which is
@@ -7899,7 +7898,7 @@
private static class DummyRequestFocusController implements RequestFocusController {
public boolean acceptRequestFocus(Component from, Component to,
boolean temporary, boolean focusedWindowChangeAllowed,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
return true;
}
@@ -7983,7 +7982,7 @@
Component toFocus = getNextFocusCandidate();
boolean res = false;
if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) {
- res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD);
+ res = toFocus.requestFocusInWindow(FocusEvent.Cause.TRAVERSAL_FORWARD);
}
if (clearOnFailure && !res) {
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
@@ -8063,7 +8062,7 @@
toFocus = policy.getDefaultComponent(rootAncestor);
}
if (toFocus != null) {
- res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD);
+ res = toFocus.requestFocusInWindow(FocusEvent.Cause.TRAVERSAL_BACKWARD);
}
}
if (clearOnFailure && !res) {
@@ -8108,7 +8107,7 @@
KeyboardFocusManager.getCurrentKeyboardFocusManager().
setGlobalCurrentFocusCycleRootPriv(fcr);
- rootAncestor.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
+ rootAncestor.requestFocus(FocusEvent.Cause.TRAVERSAL_UP);
} else {
Window window = getContainingWindow();
@@ -8118,7 +8117,7 @@
if (toFocus != null) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
setGlobalCurrentFocusCycleRootPriv(window);
- toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
+ toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_UP);
}
}
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Container.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -55,7 +55,6 @@
import sun.awt.AppContext;
import sun.awt.AWTAccessor;
-import sun.awt.CausedFocusEvent;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
@@ -3515,7 +3514,7 @@
Component toFocus = getFocusTraversalPolicy().
getDefaultComponent(this);
if (toFocus != null) {
- toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
+ toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_DOWN);
}
}
}
--- a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,6 @@
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.AWTAccessor;
-import sun.awt.CausedFocusEvent;
import sun.awt.TimedWindowEvent;
/**
@@ -165,13 +164,13 @@
boolean clearOnFailure)
{
if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.canBeFocusOwner() &&
- toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK))
+ toFocus.requestFocus(false, FocusEvent.Cause.ROLLBACK))
{
return true;
} else {
Component nextFocus = toFocus.getNextFocusCandidate();
if (nextFocus != null && nextFocus != vetoedComponent &&
- nextFocus.requestFocusInWindow(CausedFocusEvent.Cause.ROLLBACK))
+ nextFocus.requestFocusInWindow(FocusEvent.Cause.ROLLBACK))
{
return true;
} else if (clearOnFailure) {
@@ -431,13 +430,13 @@
tempLost, toFocus);
}
if (tempLost != null) {
- tempLost.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
+ tempLost.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
}
if (toFocus != null && toFocus != tempLost) {
// If there is a component which requested focus when this window
// was inactive it expects to receive focus after activation.
- toFocus.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
+ toFocus.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
}
}
@@ -490,8 +489,6 @@
case FocusEvent.FOCUS_GAINED: {
FocusEvent fe = (FocusEvent)e;
- CausedFocusEvent.Cause cause = (fe instanceof CausedFocusEvent) ?
- ((CausedFocusEvent)fe).getCause() : CausedFocusEvent.Cause.UNKNOWN;
Component oldFocusOwner = getGlobalFocusOwner();
Component newFocusOwner = fe.getComponent();
if (oldFocusOwner == newFocusOwner) {
@@ -509,10 +506,10 @@
if (oldFocusOwner != null) {
boolean isEventDispatched =
sendMessage(oldFocusOwner,
- new CausedFocusEvent(oldFocusOwner,
+ new FocusEvent(oldFocusOwner,
FocusEvent.FOCUS_LOST,
fe.isTemporary(),
- newFocusOwner, cause));
+ newFocusOwner, fe.getCause()));
// Failed to dispatch, clear by ourselves
if (!isEventDispatched) {
setGlobalFocusOwner(null);
@@ -552,7 +549,7 @@
// Refuse focus on a disabled component if the focus event
// isn't of UNKNOWN reason (i.e. not a result of a direct request
// but traversal, activation or system generated).
- (newFocusOwner.isEnabled() || cause.equals(CausedFocusEvent.Cause.UNKNOWN))))
+ (newFocusOwner.isEnabled() || fe.getCause().equals(FocusEvent.Cause.UNKNOWN))))
{
// we should not accept focus on such component, so reject it.
dequeueKeyEvents(-1, newFocusOwner);
@@ -601,10 +598,10 @@
Component realOppositeComponent = this.realOppositeComponentWR.get();
if (realOppositeComponent != null &&
realOppositeComponent != fe.getOppositeComponent()) {
- fe = new CausedFocusEvent(newFocusOwner,
+ fe = new FocusEvent(newFocusOwner,
FocusEvent.FOCUS_GAINED,
fe.isTemporary(),
- realOppositeComponent, cause);
+ realOppositeComponent, fe.getCause());
((AWTEvent) fe).isPosted = true;
}
return typeAheadAssertions(newFocusOwner, fe);
@@ -729,10 +726,10 @@
oppositeComp = oppositeWindow;
}
sendMessage(currentFocusOwner,
- new CausedFocusEvent(currentFocusOwner,
+ new FocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
true,
- oppositeComp, CausedFocusEvent.Cause.ACTIVATION));
+ oppositeComp, FocusEvent.Cause.ACTIVATION));
}
setGlobalFocusedWindow(null);
--- a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,6 @@
import sun.awt.AppContext;
import sun.awt.SunToolkit;
-import sun.awt.CausedFocusEvent;
import sun.awt.KeyboardFocusManagerPeerProvider;
import sun.awt.AWTAccessor;
@@ -124,7 +123,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
@@ -2164,9 +2163,9 @@
private static final class LightweightFocusRequest {
final Component component;
final boolean temporary;
- final CausedFocusEvent.Cause cause;
+ final FocusEvent.Cause cause;
- LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
+ LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause) {
this.component = component;
this.temporary = temporary;
this.cause = cause;
@@ -2190,7 +2189,7 @@
}
HeavyweightFocusRequest(Component heavyweight, Component descendant,
- boolean temporary, CausedFocusEvent.Cause cause) {
+ boolean temporary, FocusEvent.Cause cause) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (heavyweight == null) {
log.fine("Assertion (heavyweight != null) failed");
@@ -2202,7 +2201,7 @@
addLightweightRequest(descendant, temporary, cause);
}
boolean addLightweightRequest(Component descendant,
- boolean temporary, CausedFocusEvent.Cause cause) {
+ boolean temporary, FocusEvent.Cause cause) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
@@ -2314,7 +2313,7 @@
hwFocusRequest =
new HeavyweightFocusRequest(heavyweight, descendant,
- temporary, CausedFocusEvent.Cause.UNKNOWN);
+ temporary, FocusEvent.Cause.UNKNOWN);
heavyweightRequests.add(hwFocusRequest);
if (currentFocusOwner != null) {
@@ -2379,7 +2378,7 @@
*/
static int shouldNativelyFocusHeavyweight
(Component heavyweight, Component descendant, boolean temporary,
- boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
+ boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)
{
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (heavyweight == null) {
@@ -2445,7 +2444,7 @@
if (currentFocusOwner != null) {
FocusEvent currentFocusOwnerEvent =
- new CausedFocusEvent(currentFocusOwner,
+ new FocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
temporary, descendant, cause);
// Fix 5028014. Rolled out.
@@ -2454,7 +2453,7 @@
currentFocusOwnerEvent);
}
FocusEvent newFocusOwnerEvent =
- new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
+ new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
temporary, currentFocusOwner, cause);
// Fix 5028014. Rolled out.
// SunToolkit.postPriorityEvent(newFocusOwnerEvent);
@@ -2670,13 +2669,13 @@
* lw requests.
*/
if (currentFocusOwner != null) {
- currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
+ currentFocusOwnerEvent = new FocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
lwFocusRequest.temporary,
lwFocusRequest.component, lwFocusRequest.cause);
}
FocusEvent newFocusOwnerEvent =
- new CausedFocusEvent(lwFocusRequest.component,
+ new FocusEvent(lwFocusRequest.component,
FocusEvent.FOCUS_GAINED,
lwFocusRequest.temporary,
currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
@@ -2726,8 +2725,8 @@
{
temporary = true;
}
- return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
- CausedFocusEvent.Cause.NATIVE_SYSTEM);
+ return new FocusEvent(source, fe.getID(), temporary, opposite,
+ FocusEvent.Cause.UNEXPECTED);
}
}
@@ -2802,7 +2801,7 @@
// 'opposite' will be fixed by
// DefaultKeyboardFocusManager.realOppositeComponent
- return new CausedFocusEvent(newSource,
+ return new FocusEvent(newSource,
FocusEvent.FOCUS_GAINED, temporary,
opposite, lwFocusRequest.cause);
}
@@ -2815,8 +2814,8 @@
// If it arrives as the result of activation we should skip it
// This event will not have appropriate request record and
// on arrival there will be already some focus owner set.
- return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
- null, CausedFocusEvent.Cause.ACTIVATION);
+ return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
+ null, FocusEvent.Cause.ACTIVATION);
}
return retargetUnexpectedFocusEvent(fe);
@@ -2839,9 +2838,9 @@
if (currentFocusOwner != null) {
// Call to KeyboardFocusManager.clearGlobalFocusOwner()
heavyweightRequests.removeFirst();
- return new CausedFocusEvent(currentFocusOwner,
+ return new FocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST, false, null,
- CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
+ FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
}
// Otherwise, fall through to failure case below
@@ -2850,9 +2849,9 @@
{
// Focus leaving application
if (currentFocusOwner != null) {
- return new CausedFocusEvent(currentFocusOwner,
+ return new FocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
- true, null, CausedFocusEvent.Cause.ACTIVATION);
+ true, null, FocusEvent.Cause.ACTIVATION);
} else {
return fe;
}
@@ -2878,15 +2877,15 @@
? true
: lwFocusRequest.temporary;
- return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
+ return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
temporary, lwFocusRequest.component, lwFocusRequest.cause);
} else if (focusedWindowChanged(opposite, currentFocusOwner)) {
// If top-level changed there might be no focus request in a list
// But we know the opposite, we now it is temporary - dispatch the event.
if (!fe.isTemporary() && currentFocusOwner != null) {
// Create copy of the event with only difference in temporary parameter.
- fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
- true, opposite, CausedFocusEvent.Cause.ACTIVATION);
+ fe = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
+ true, opposite, FocusEvent.Cause.ACTIVATION);
}
return fe;
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Window.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -52,7 +52,6 @@
import sun.awt.AWTAccessor;
import sun.awt.AWTPermissions;
import sun.awt.AppContext;
-import sun.awt.CausedFocusEvent;
import sun.awt.DebugSettings;
import sun.awt.SunToolkit;
import sun.awt.util.IdentityArrayList;
@@ -2599,7 +2598,7 @@
{
Component toFocus =
KeyboardFocusManager.getMostRecentFocusOwner(owner);
- if (toFocus != null && toFocus.requestFocus(false, CausedFocusEvent.Cause.ACTIVATION)) {
+ if (toFocus != null && toFocus.requestFocus(false, FocusEvent.Cause.ACTIVATION)) {
return;
}
}
--- a/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,9 @@
package java.awt.event;
import java.awt.Component;
+import java.io.ObjectStreamException;
+
+import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
@@ -51,6 +54,10 @@
* the FOCUS_GAINED and FOCUS_LOST event ids; the level may be distinguished in
* the event using the isTemporary() method.
* <p>
+ * Every {@code FocusEvent} records its cause - the reason why this event was
+ * generated. The cause is assigned during the focus event creation and may be
+ * retrieved by calling {@link #getCause}.
+ * <p>
* An unspecified behavior will be caused if the {@code id} parameter
* of any particular {@code FocusEvent} instance is not
* in the range from {@code FOCUS_FIRST} to {@code FOCUS_LAST}.
@@ -66,6 +73,61 @@
public class FocusEvent extends ComponentEvent {
/**
+ * This enum represents the cause of a {@code FocusEvent}- the reason why it
+ * occurred. Possible reasons include mouse events, keyboard focus
+ * traversal, window activation.
+ * If no cause is provided then the reason is {@code UNKNOWN}.
+ *
+ * @since 9
+ */
+ public enum Cause {
+ /**
+ * The default value.
+ */
+ UNKNOWN,
+ /**
+ * An activating mouse event.
+ */
+ MOUSE_EVENT,
+ /**
+ * A focus traversal action with unspecified direction.
+ */
+ TRAVERSAL,
+ /**
+ * An up-cycle focus traversal action.
+ */
+ TRAVERSAL_UP,
+ /**
+ * A down-cycle focus traversal action.
+ */
+ TRAVERSAL_DOWN,
+ /**
+ * A forward focus traversal action.
+ */
+ TRAVERSAL_FORWARD,
+ /**
+ * A backward focus traversal action.
+ */
+ TRAVERSAL_BACKWARD,
+ /**
+ * Restoring focus after a focus request has been rejected.
+ */
+ ROLLBACK,
+ /**
+ * A system action causing an unexpected focus change.
+ */
+ UNEXPECTED,
+ /**
+ * An activation of a toplevel window.
+ */
+ ACTIVATION,
+ /**
+ * Clearing global focus owner.
+ */
+ CLEAR_GLOBAL_FOCUS_OWNER
+ }
+
+ /**
* The first number in the range of ids used for focus events.
*/
public static final int FOCUS_FIRST = 1004;
@@ -86,6 +148,16 @@
public static final int FOCUS_LOST = 1 + FOCUS_FIRST; //Event.LOST_FOCUS
/**
+ * A focus event has the reason why this event was generated.
+ * The cause is set during the focus event creation.
+ *
+ * @serial
+ * @see #getCause()
+ * @since 9
+ */
+ private final Cause cause;
+
+ /**
* A focus event can have two different levels, permanent and temporary.
* It will be set to true if some operation takes away the focus
* temporarily and intends on getting it back once the event is completed.
@@ -115,7 +187,8 @@
/**
* Constructs a {@code FocusEvent} object with the
- * specified temporary state and opposite {@code Component}.
+ * specified temporary state, opposite {@code Component} and the
+ * {@code Cause.UNKNOWN} cause.
* The opposite {@code Component} is the other
* {@code Component} involved in this focus change.
* For a {@code FOCUS_GAINED} event, this is the
@@ -142,13 +215,57 @@
* @see #getID()
* @see #isTemporary()
* @see #getOppositeComponent()
+ * @see Cause#UNKNOWN
* @since 1.4
*/
public FocusEvent(Component source, int id, boolean temporary,
Component opposite) {
+ this(source, id, temporary, opposite, Cause.UNKNOWN);
+ }
+
+ /**
+ * Constructs a {@code FocusEvent} object with the
+ * specified temporary state, opposite {@code Component} and the cause.
+ * The opposite {@code Component} is the other
+ * {@code Component} involved in this focus change.
+ * For a {@code FOCUS_GAINED} event, this is the
+ * {@code Component} that lost focus. For a
+ * {@code FOCUS_LOST} event, this is the {@code Component}
+ * that gained focus. If this focus change occurs with a native
+ * application, with a Java application in a different VM,
+ * or with no other {@code Component}, then the opposite
+ * {@code Component} is {@code null}.
+ * <p> This method throws an
+ * {@code IllegalArgumentException} if {@code source} or {@code cause}
+ * is {@code null}.
+ *
+ * @param source The {@code Component} that originated the event
+ * @param id An integer indicating the type of event.
+ * For information on allowable values, see
+ * the class description for {@link FocusEvent}
+ * @param temporary Equals {@code true} if the focus change is temporary;
+ * {@code false} otherwise
+ * @param opposite The other Component involved in the focus change,
+ * or {@code null}
+ * @param cause The focus event cause.
+ * @throws IllegalArgumentException if {@code source} equals {@code null}
+ * or if {@code cause} equals {@code null}
+ * @see #getSource()
+ * @see #getID()
+ * @see #isTemporary()
+ * @see #getOppositeComponent()
+ * @see Cause
+ * @since 9
+ */
+ public FocusEvent(Component source, int id, boolean temporary,
+ Component opposite, Cause cause) {
super(source, id);
+ if (cause == null) {
+ throw new IllegalArgumentException("null cause");
+ }
this.temporary = temporary;
this.opposite = opposite;
+ this.cause = cause;
}
/**
@@ -220,8 +337,8 @@
return (SunToolkit.targetToAppContext(opposite) ==
AppContext.getAppContext())
- ? opposite
- : null;
+ ? opposite
+ : null;
}
/**
@@ -233,17 +350,56 @@
public String paramString() {
String typeStr;
switch(id) {
- case FOCUS_GAINED:
- typeStr = "FOCUS_GAINED";
- break;
- case FOCUS_LOST:
- typeStr = "FOCUS_LOST";
- break;
- default:
- typeStr = "unknown type";
+ case FOCUS_GAINED:
+ typeStr = "FOCUS_GAINED";
+ break;
+ case FOCUS_LOST:
+ typeStr = "FOCUS_LOST";
+ break;
+ default:
+ typeStr = "unknown type";
}
return typeStr + (temporary ? ",temporary" : ",permanent") +
- ",opposite=" + getOppositeComponent();
+ ",opposite=" + getOppositeComponent() + ",cause=" + getCause();
+ }
+
+ /**
+ * Returns the event cause.
+ *
+ * @return one of {@link Cause} values
+ * @since 9
+ */
+ public final Cause getCause() {
+ return cause;
}
-}
+ /**
+ * Checks if this deserialized {@code FocusEvent} instance is compatible
+ * with the current specification which implies that focus event has
+ * non-null {@code cause} value. If the check fails a new {@code FocusEvent}
+ * instance is returned which {@code cause} field equals to
+ * {@link Cause#UNKNOWN} and its other fields have the same values as in
+ * this {@code FocusEvent} instance.
+ *
+ * @serial
+ * @see #cause
+ * @since 9
+ */
+ @SuppressWarnings("serial")
+ Object readResolve() throws ObjectStreamException {
+ if (cause != null) {
+ return this;
+ }
+ FocusEvent focusEvent = new FocusEvent(new Component(){}, getID(),
+ isTemporary(), getOppositeComponent());
+ focusEvent.setSource(null);
+ focusEvent.consumed = consumed;
+
+ AWTAccessor.AWTEventAccessor accessor =
+ AWTAccessor.getAWTEventAccessor();
+ accessor.setBData(focusEvent, accessor.getBData(this));
+ return focusEvent;
+ }
+
+
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java Fri May 06 06:23:30 2016 -0700
@@ -79,7 +79,7 @@
* will be ignored.
* <li>The identity of the value does not matter, only the actual
* value. For example, {@code TextAttribute.WEIGHT_BOLD} and
- * {@code new Float(2.0)}
+ * {@code Float.valueOf(2.0f)}
* indicate the same {@code WEIGHT}.
* <li>Attribute values of type {@code Number} (used for
* {@code WEIGHT}, {@code WIDTH}, {@code POSTURE},
--- a/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java Fri May 06 06:23:30 2016 -0700
@@ -105,7 +105,7 @@
String s = System.getProperty("estLines");
if (s != null) {
try {
- Float f = new Float(s);
+ Float f = Float.valueOf(s);
EST_LINES = f.floatValue();
}
catch(NumberFormatException e) {
--- a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java Fri May 06 06:23:30 2016 -0700
@@ -392,7 +392,7 @@
* the specified parameter.
*/
public ParameterBlock add(float f) {
- return add(new Float(f));
+ return add(Float.valueOf(f));
}
/**
@@ -403,7 +403,7 @@
* the specified parameter.
*/
public ParameterBlock add(double d) {
- return add(new Double(d));
+ return add(Double.valueOf(d));
}
/**
@@ -521,7 +521,7 @@
* the specified parameter.
*/
public ParameterBlock set(float f, int index) {
- return set(new Float(f), index);
+ return set(Float.valueOf(f), index);
}
/**
@@ -537,7 +537,7 @@
* the specified parameter.
*/
public ParameterBlock set(double d, int index) {
- return set(new Double(d), index);
+ return set(Double.valueOf(d), index);
}
/**
--- a/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,12 @@
import java.awt.*;
import java.awt.event.PaintEvent;
+import java.awt.event.FocusEvent.Cause;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
-import sun.awt.CausedFocusEvent;
import sun.java2d.pipe.Region;
@@ -343,7 +343,7 @@
*/
boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
- CausedFocusEvent.Cause cause);
+ Cause cause);
/**
* Returns {@code true} when the component takes part in the focus
--- a/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java Fri May 06 06:23:30 2016 -0700
@@ -577,6 +577,8 @@
/**
* Gets the name of the printing user.
* @return the name of the printing user
+ * @throws SecurityException if a security manager exists and
+ * PropertyPermission - user.name is not given in the policy file
*/
public abstract String getUserName();
--- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
import java.awt.*;
import java.awt.event.*;
-import java.awt.peer.LightweightPeer;
import java.applet.Applet;
@@ -57,7 +56,6 @@
import sun.awt.AWTAccessor;
import sun.awt.SunToolkit;
import sun.swing.SwingUtilities2;
-import sun.swing.UIClientPropertyKey;
/**
* The base class for all Swing components except top-level containers.
@@ -3558,7 +3556,7 @@
new sun.awt.RequestFocusController() {
public boolean acceptRequestFocus(Component from, Component to,
boolean temporary, boolean focusedWindowChangeAllowed,
- sun.awt.CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
if ((to == null) || !(to instanceof JComponent)) {
return true;
--- a/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java Fri May 06 06:23:30 2016 -0700
@@ -98,7 +98,7 @@
* <PRE>
* layeredPane.add(child, JLayeredPane.DEFAULT_LAYER);
* or
- * layeredPane.add(child, new Integer(10));
+ * layeredPane.add(child, Integer.valueOf.valueOf(10));
* </PRE>
* The layer attribute can also be set on a Component by calling<PRE>
* layeredPaneParent.setLayer(child, 10)</PRE>
@@ -162,23 +162,23 @@
@SuppressWarnings("serial")
public class JLayeredPane extends JComponent implements Accessible {
/// Watch the values in getObjectForLayer()
- /** Convenience object defining the Default layer. Equivalent to new Integer(0).*/
+ /** Convenience object defining the Default layer. Equivalent to Integer.valueOf(0).*/
public static final Integer DEFAULT_LAYER = 0;
- /** Convenience object defining the Palette layer. Equivalent to new Integer(100).*/
+ /** Convenience object defining the Palette layer. Equivalent to Integer.valueOf(100).*/
public static final Integer PALETTE_LAYER = 100;
- /** Convenience object defining the Modal layer. Equivalent to new Integer(200).*/
+ /** Convenience object defining the Modal layer. Equivalent to Integer.valueOf(200).*/
public static final Integer MODAL_LAYER = 200;
- /** Convenience object defining the Popup layer. Equivalent to new Integer(300).*/
+ /** Convenience object defining the Popup layer. Equivalent to Integer.valueOf(300).*/
public static final Integer POPUP_LAYER = 300;
- /** Convenience object defining the Drag layer. Equivalent to new Integer(400).*/
+ /** Convenience object defining the Drag layer. Equivalent to Integer.valueOf(400).*/
public static final Integer DRAG_LAYER = 400;
/** Convenience object defining the Frame Content layer.
* This layer is normally only use to position the contentPane and menuBar
* components of JFrame.
- * Equivalent to new Integer(-30000).
+ * Equivalent to Integer.valueOf(-30000).
* @see JFrame
*/
- public static final Integer FRAME_CONTENT_LAYER = new Integer(-30000);
+ public static final Integer FRAME_CONTENT_LAYER = -30000;
/** Bound property */
public static final String LAYER_PROPERTY = "layeredContainerLayer";
--- a/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java Fri May 06 06:23:30 2016 -0700
@@ -478,7 +478,7 @@
if (format == null) {
format = NumberFormat.getPercentInstance();
}
- return format.format(new Double(getPercentComplete()));
+ return format.format(Double.valueOf(getPercentComplete()));
}
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Fri May 06 06:23:30 2016 -0700
@@ -81,7 +81,7 @@
* TableModel dataModel = new AbstractTableModel() {
* public int getColumnCount() { return 10; }
* public int getRowCount() { return 10;}
- * public Object getValueAt(int row, int col) { return new Integer(row*col); }
+ * public Object getValueAt(int row, int col) { return Integer.valueOf(row*col); }
* };
* JTable table = new JTable(dataModel);
* JScrollPane scrollpane = new JScrollPane(table);
--- a/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java Fri May 06 06:23:30 2016 -0700
@@ -51,10 +51,10 @@
* range zero to one hundred, with
* fifty as the initial value, one could write:
* <pre>
- * Integer value = new Integer(50);
- * Integer min = new Integer(0);
- * Integer max = new Integer(100);
- * Integer step = new Integer(1);
+ * Integer value = Integer.valueOf(50);
+ * Integer min = Integer.valueOf(0);
+ * Integer max = Integer.valueOf(100);
+ * Integer step = Integer.valueOf(1);
* SpinnerNumberModel model = new SpinnerNumberModel(value, min, max, step);
* int fifty = model.getNumber().intValue();
* </pre>
@@ -175,7 +175,8 @@
* <code>minimum <= value <= maximum</code>
*/
public SpinnerNumberModel(double value, double minimum, double maximum, double stepSize) {
- this(new Double(value), new Double(minimum), new Double(maximum), new Double(stepSize));
+ this(Double.valueOf(value), Double.valueOf(minimum),
+ Double.valueOf(maximum), Double.valueOf(stepSize));
}
@@ -337,10 +338,10 @@
if ((value instanceof Float) || (value instanceof Double)) {
double v = value.doubleValue() + (stepSize.doubleValue() * (double)dir);
if (value instanceof Double) {
- newValue = new Double(v);
+ newValue = Double.valueOf(v);
}
else {
- newValue = new Float(v);
+ newValue = Float.valueOf((float)v);
}
} else {
long v = value.longValue() + (stepSize.longValue() * (long)dir);
--- a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java Fri May 06 06:23:30 2016 -0700
@@ -846,14 +846,46 @@
}
/**
+ * Check whether MouseEvent contains speficied mouse button or
+ * mouse button down mask based on MouseEvent ID.
+ *
+ * @param anEvent a MouseEvent object
+ * @param mouseButton mouse button type
+ * @param mouseButtonDownMask mouse button down mask event modifier
+ *
+ * @return true if the anEvent contains speficied mouseButton or
+ * mouseButtonDownMask based on MouseEvent ID.
+ */
+ private static boolean checkMouseButton(MouseEvent anEvent,
+ int mouseButton,
+ int mouseButtonDownMask)
+ {
+ switch (anEvent.getID()) {
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ case MouseEvent.MOUSE_CLICKED:
+ return (anEvent.getButton() == mouseButton);
+
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ case MouseEvent.MOUSE_DRAGGED:
+ return ((anEvent.getModifiersEx() & mouseButtonDownMask) != 0);
+
+ default:
+ return ((anEvent.getModifiersEx() & mouseButtonDownMask) != 0 ||
+ anEvent.getButton() == mouseButton);
+ }
+ }
+
+ /**
* Returns true if the mouse event specifies the left mouse button.
*
* @param anEvent a MouseEvent object
* @return true if the left mouse button was active
*/
public static boolean isLeftMouseButton(MouseEvent anEvent) {
- return ((anEvent.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0 ||
- anEvent.getButton() == MouseEvent.BUTTON1);
+ return checkMouseButton(anEvent, MouseEvent.BUTTON1,
+ InputEvent.BUTTON1_DOWN_MASK);
}
/**
@@ -863,8 +895,8 @@
* @return true if the middle mouse button was active
*/
public static boolean isMiddleMouseButton(MouseEvent anEvent) {
- return ((anEvent.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0 ||
- anEvent.getButton() == MouseEvent.BUTTON2);
+ return checkMouseButton(anEvent, MouseEvent.BUTTON2,
+ InputEvent.BUTTON2_DOWN_MASK);
}
/**
@@ -874,8 +906,8 @@
* @return true if the right mouse button was active
*/
public static boolean isRightMouseButton(MouseEvent anEvent) {
- return ((anEvent.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ||
- anEvent.getButton() == MouseEvent.BUTTON3);
+ return checkMouseButton(anEvent, MouseEvent.BUTTON3,
+ InputEvent.BUTTON3_DOWN_MASK);
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIClientPropertyKey.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.swing;
+
+/**
+ * This interface is used only for tagging keys for client properties for
+ * {@code JComponent} set by UI which needs to be cleared on {@literal L&F}
+ * change and serialization.
+ * <p>
+ * All such keys are removed from client properties in
+ * {@code JComponent.setUI()} method after uninstalling old UI and before
+ * installing the new one. They are also removed prior to serialization.
+ *
+ * @author Igor Kushnirskiy
+ * @since 9
+ */
+public interface UIClientPropertyKey {
+}
--- a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java Fri May 06 06:23:30 2016 -0700
@@ -120,7 +120,7 @@
Object[] uiDefaults = {
"Font", new Font("Dialog", Font.BOLD, 12),
"Color", Color.red,
- "five", new Integer(5)
+ "five", Integer.valueOf(5)
}
UIDefaults myDefaults = new UIDefaults(uiDefaults);
* </pre>
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java Fri May 06 06:23:30 2016 -0700
@@ -134,7 +134,7 @@
new BorderUIResource.LineBorderUIResource(getPrimary1());
// .30 0 DDE8F3 white secondary2
java.util.List<?> buttonGradient = Arrays.asList(
- new Object[] {new Float(.3f), new Float(0f),
+ new Object[] {Float.valueOf(.3f), Float.valueOf(0f),
new ColorUIResource(0xDDE8F3), getWhite(), getSecondary2() });
// Other possible properties that aren't defined:
@@ -150,7 +150,7 @@
Object directoryIcon = getIconResource("icons/ocean/directory.gif");
Object fileIcon = getIconResource("icons/ocean/file.gif");
java.util.List<?> sliderGradient = Arrays.asList(new Object[] {
- new Float(.3f), new Float(.2f),
+ Float.valueOf(.3f), Float.valueOf(.2f),
c8ddf2, getWhite(), new ColorUIResource(SECONDARY2) });
Object[] defaults = new Object[] {
@@ -192,7 +192,7 @@
"Menu.opaque", Boolean.FALSE,
"MenuBar.gradient", Arrays.asList(new Object[] {
- new Float(1f), new Float(0f),
+ Float.valueOf(1f), Float.valueOf(0f),
getWhite(), dadada,
new ColorUIResource(dadada) }),
"MenuBar.borderColor", cccccc,
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java Fri May 06 06:23:30 2016 -0700
@@ -139,7 +139,6 @@
}
}
- context.dispose();
return dim;
}
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java Fri May 06 06:23:30 2016 -0700
@@ -61,7 +61,6 @@
return;
}
ui.paintBorder(context, g, x, y, width, height);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java Fri May 06 06:23:30 2016 -0700
@@ -105,7 +105,6 @@
}
}
- context.dispose();
}
/**
@@ -125,7 +124,6 @@
SynthContext context = getContext(b, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -226,7 +224,6 @@
else {
baseline = textRect.y + fm.getAscent();
}
- context.dispose();
return baseline;
}
@@ -253,7 +250,6 @@
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
- context.dispose();
}
/**
@@ -270,7 +266,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -321,7 +316,6 @@
protected Icon getDefaultIcon(AbstractButton b) {
SynthContext context = getContext(b);
Icon icon = context.getStyle().getIcon(context, getPropertyPrefix() + "icon");
- context.dispose();
return icon;
}
@@ -473,7 +467,6 @@
b.getVerticalTextPosition(), b.getIconTextGap(),
b.getDisplayedMnemonicIndex());
- ss.dispose();
return size;
}
@@ -494,7 +487,6 @@
b.getVerticalTextPosition(), b.getIconTextGap(),
b.getDisplayedMnemonicIndex());
- ss.dispose();
return size;
}
@@ -516,7 +508,6 @@
b.getVerticalTextPosition(), b.getIconTextGap(),
b.getDisplayedMnemonicIndex());
- ss.dispose();
return size;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java Fri May 06 06:23:30 2016 -0700
@@ -65,7 +65,6 @@
SynthContext context = getContext(chooser, ENABLED);
AbstractColorChooserPanel[] panels = (AbstractColorChooserPanel[])
context.getStyle().get(context, "ColorChooser.panels");
- context.dispose();
if (panels == null) {
panels = ColorChooserComponentFactory.getDefaultChooserPanels();
@@ -85,7 +84,6 @@
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -96,7 +94,6 @@
SynthContext context = getContext(chooser, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
super.uninstallDefaults();
}
@@ -155,7 +152,6 @@
context.getPainter().paintColorChooserBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -172,7 +168,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java Fri May 06 06:23:30 2016 -0700
@@ -144,7 +144,6 @@
forceOpaque = style.getBoolean(context,
"ComboBox.forceOpaque", false);
}
- context.dispose();
if(listBox != null) {
SynthLookAndFeel.updateStyles(listBox);
@@ -182,7 +181,6 @@
SynthContext context = getContext(comboBox, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -323,7 +321,6 @@
context.getPainter().paintComboBoxBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -340,7 +337,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java Fri May 06 06:23:30 2016 -0700
@@ -24,8 +24,6 @@
*/
package javax.swing.plaf.synth;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.JComponent;
/**
@@ -40,7 +38,6 @@
* @author Scott Violet
*/
public class SynthContext {
- private static final Queue<SynthContext> queue = new ConcurrentLinkedQueue<>();
private JComponent component;
private Region region;
@@ -54,19 +51,15 @@
static SynthContext getContext(JComponent component,
Region region, SynthStyle style,
int state) {
- SynthContext context = queue.poll();
- if (context == null) {
- context = new SynthContext();
- }
- context.reset(component, region, style, state);
+ SynthContext context = new SynthContext();
+ context.component = component;
+ context.region = region;
+ context.style = style;
+ context.state = state;
return context;
}
- static void releaseContext(SynthContext context) {
- queue.offer(context);
- }
-
- SynthContext() {
+ private SynthContext() {
}
/**
@@ -86,7 +79,11 @@
throw new NullPointerException(
"You must supply a non-null component, region and style");
}
- reset(component, region, style, state);
+
+ this.component = component;
+ this.region = region;
+ this.style = style;
+ this.state = state;
}
@@ -147,23 +144,6 @@
}
/**
- * Resets the state of the Context.
- */
- void reset(JComponent component, Region region, SynthStyle style,
- int state) {
- this.component = component;
- this.region = region;
- this.style = style;
- this.state = state;
- }
-
- void dispose() {
- this.component = null;
- this.style = null;
- releaseContext(this);
- }
-
- /**
* Convenience method to get the Painter from the current SynthStyle.
* This will NEVER return null.
*/
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java Fri May 06 06:23:30 2016 -0700
@@ -41,7 +41,6 @@
}
SynthContext context = ((SynthUI)ui).getContext(c);
Object value = context.getStyle().get(context, key);
- context.dispose();
return value;
}
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java Fri May 06 06:23:30 2016 -0700
@@ -121,7 +121,6 @@
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -131,7 +130,6 @@
protected void uninstallDefaults() {
SynthContext context = getContext(desktopIcon, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -171,7 +169,6 @@
context.getPainter().paintDesktopIconBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -188,7 +185,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -119,7 +119,6 @@
uninstallKeyboardActions();
installKeyboardActions();
}
- context.dispose();
}
/**
@@ -143,7 +142,6 @@
SynthContext context = getContext(desktop, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
if (taskBar != null) {
@@ -460,7 +458,6 @@
context.getPainter().paintDesktopPaneBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -477,7 +474,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -83,7 +83,6 @@
c.putClientProperty("caretAspectRatio", null);
style.uninstallDefaults(context);
- context.dispose();
style = null;
Object clientProperty =
@@ -127,7 +126,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -165,7 +163,6 @@
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java Fri May 06 06:23:30 2016 -0700
@@ -138,7 +138,6 @@
}
}
}
- context.dispose();
}
protected void installDefaults() {
@@ -149,7 +148,6 @@
protected void uninstallDefaults() {
SynthContext context = getContext(this, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
JInternalFrame.JDesktopIcon di = frame.getDesktopIcon();
if(di != null && di.getComponentPopupMenu() == systemPopupMenu) {
@@ -235,7 +233,6 @@
context.getPainter().paintInternalFrameTitlePaneBackground(context,
g, 0, 0, getWidth(), getHeight());
paint(context, g);
- context.dispose();
}
protected void paint(SynthContext context, Graphics g) {
@@ -321,7 +318,6 @@
SynthContext context = getContext(this);
LayoutManager lm =
(LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout");
- context.dispose();
return (lm != null) ? lm : new SynthTitlePaneLayout();
}
@@ -362,7 +358,6 @@
Image.SCALE_SMOOTH));
}
}
- context.dispose();
menuButton.setIcon(frameIcon);
}
@@ -433,7 +428,6 @@
Insets insets = getInsets();
height += insets.top + insets.bottom;
width += insets.left + insets.right;
- context.dispose();
return new Dimension(width, height);
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java Fri May 06 06:23:30 2016 -0700
@@ -118,7 +118,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -128,7 +127,6 @@
protected void uninstallDefaults() {
SynthContext context = getContext(frame, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
if(frame.getLayout() == internalFrameLayout) {
frame.setLayout(null);
@@ -216,7 +214,6 @@
context.getPainter().paintInternalFrameBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -233,7 +230,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java Fri May 06 06:23:30 2016 -0700
@@ -67,7 +67,6 @@
void updateStyle(JLabel c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -78,7 +77,6 @@
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -150,7 +148,6 @@
else {
baseline = textRect.y + fm.getAscent();
}
- context.dispose();
return baseline;
}
@@ -174,7 +171,6 @@
context.getPainter().paintLabelBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -191,7 +187,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -242,7 +237,6 @@
label.getVerticalTextPosition(), label.getIconTextGap(),
label.getDisplayedMnemonicIndex());
- context.dispose();
return size;
}
@@ -263,7 +257,6 @@
label.getVerticalTextPosition(), label.getIconTextGap(),
label.getDisplayedMnemonicIndex());
- context.dispose();
return size;
}
@@ -284,7 +277,6 @@
label.getVerticalTextPosition(), label.getIconTextGap(),
label.getDisplayedMnemonicIndex());
- context.dispose();
return size;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java Fri May 06 06:23:30 2016 -0700
@@ -75,7 +75,6 @@
SynthLookAndFeel.update(context, g);
context.getPainter().paintListBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
- context.dispose();
paint(g, c);
}
@@ -162,7 +161,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -175,7 +173,6 @@
SynthContext context = getContext(list, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java Fri May 06 06:23:30 2016 -0700
@@ -976,7 +976,6 @@
if (currBG != null && !currBG.equals(lastBG)) {
comp.repaint();
}
- context.dispose();
}
}
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java Fri May 06 06:23:30 2016 -0700
@@ -83,7 +83,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -94,7 +93,6 @@
SynthContext context = getContext(menuBar, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -143,7 +141,6 @@
context.getPainter().paintMenuBarBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -160,7 +157,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java Fri May 06 06:23:30 2016 -0700
@@ -124,13 +124,11 @@
installKeyboardActions();
}
}
- context.dispose();
SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
ENABLED);
accStyle = SynthLookAndFeel.updateStyle(accContext, this);
- accContext.dispose();
}
/**
@@ -140,13 +138,11 @@
protected void uninstallDefaults() {
SynthContext context = getContext(menuItem, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR, ENABLED);
accStyle.uninstallDefaults(accContext);
- accContext.dispose();
accStyle = null;
super.uninstallDefaults();
@@ -218,8 +214,6 @@
defaultTextIconGap, acceleratorDelimiter,
MenuItemLayoutHelper.useCheckAndArrow(menuItem),
getPropertyPrefix());
- context.dispose();
- accContext.dispose();
return value;
}
@@ -243,7 +237,6 @@
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
- context.dispose();
}
/**
@@ -260,7 +253,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -280,7 +272,6 @@
Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
- accContext.dispose();
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java Fri May 06 06:23:30 2016 -0700
@@ -110,13 +110,11 @@
installKeyboardActions();
}
}
- context.dispose();
SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
ENABLED);
accStyle = SynthLookAndFeel.updateStyle(accContext, this);
- accContext.dispose();
}
/**
@@ -140,13 +138,11 @@
protected void uninstallDefaults() {
SynthContext context = getContext(menuItem, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR, ENABLED);
accStyle.uninstallDefaults(accContext);
- accContext.dispose();
accStyle = null;
super.uninstallDefaults();
@@ -218,8 +214,6 @@
defaultTextIconGap, acceleratorDelimiter,
MenuItemLayoutHelper.useCheckAndArrow(menuItem),
getPropertyPrefix());
- context.dispose();
- accContext.dispose();
return value;
}
@@ -243,7 +237,6 @@
context.getPainter().paintMenuBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -260,7 +253,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -279,7 +271,6 @@
Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
- accContext.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -88,7 +88,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -99,7 +98,6 @@
SynthContext context = getContext(optionPane, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -125,7 +123,6 @@
SynthContext context = getContext(optionPane, ENABLED);
optionPane.add(Box.createVerticalStrut(context.getStyle().
getInt(context, "OptionPane.separatorPadding", 6)));
- context.dispose();
}
optionPane.add(createButtonArea());
optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
@@ -167,7 +164,6 @@
context.getPainter().paintOptionPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -184,7 +180,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -259,7 +254,6 @@
SynthContext context = getContext(optionPane, ENABLED);
cons.anchor = context.getStyle().getInt(context,
"OptionPane.messageAnchor", GridBagConstraints.CENTER);
- context.dispose();
cons.insets = new Insets(0,0,3,0);
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java Fri May 06 06:23:30 2016 -0700
@@ -108,14 +108,12 @@
SynthContext context = getContext(p, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
private void updateStyle(JPanel c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -154,7 +152,6 @@
context.getPainter().paintPanelBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -171,7 +168,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java Fri May 06 06:23:30 2016 -0700
@@ -77,7 +77,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -97,7 +96,6 @@
SynthContext context = getContext(popupMenu, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
if (popupMenu.getLayout() instanceof UIResource) {
@@ -150,7 +148,6 @@
context.getPainter().paintPopupMenuBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -167,7 +164,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java Fri May 06 06:23:30 2016 -0700
@@ -118,7 +118,6 @@
}
minBarSize = (Dimension)style.get(context, "ProgressBar.minBarSize");
glowWidth = style.getInt(context, "ProgressBar.glowWidth", 0);
- context.dispose();
}
/**
@@ -129,7 +128,6 @@
SynthContext context = getContext(progressBar, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -160,7 +158,6 @@
SynthContext context = getContext(c);
Font font = context.getStyle().getFont(context);
FontMetrics metrics = progressBar.getFontMetrics(font);
- context.dispose();
return (height - metrics.getAscent() - metrics.getDescent()) / 2 +
metrics.getAscent();
}
@@ -216,7 +213,6 @@
g, 0, 0, c.getWidth(), c.getHeight(),
progressBar.getOrientation());
paint(context, g);
- context.dispose();
}
/**
@@ -233,7 +229,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -67,7 +67,6 @@
SynthContext context = getContext(root, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -97,7 +96,6 @@
installKeyboardActions((JRootPane)c);
}
}
- context.dispose();
}
/**
@@ -120,7 +118,6 @@
context.getPainter().paintRootPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -137,7 +134,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java Fri May 06 06:23:30 2016 -0700
@@ -129,15 +129,12 @@
installKeyboardActions();
}
}
- context.dispose();
context = getContext(c, Region.SCROLL_BAR_TRACK, ENABLED);
trackStyle = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
context = getContext(c, Region.SCROLL_BAR_THUMB, ENABLED);
thumbStyle = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -165,17 +162,14 @@
protected void uninstallDefaults(){
SynthContext context = getContext(scrollbar, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
context = getContext(scrollbar, Region.SCROLL_BAR_TRACK, ENABLED);
trackStyle.uninstallDefaults(context);
- context.dispose();
trackStyle = null;
context = getContext(scrollbar, Region.SCROLL_BAR_THUMB, ENABLED);
thumbStyle.uninstallDefaults(context);
- context.dispose();
thumbStyle = null;
super.uninstallDefaults();
@@ -222,7 +216,6 @@
SynthContext context = getContext(scrollbar);
boolean value = style.getBoolean(context,
"ScrollBar.allowsAbsolutePositioning", false);
- context.dispose();
return value;
}
@@ -247,7 +240,6 @@
g, 0, 0, c.getWidth(), c.getHeight(),
scrollbar.getOrientation());
paint(context, g);
- context.dispose();
}
/**
@@ -264,7 +256,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -278,11 +269,9 @@
SynthContext subcontext = getContext(scrollbar,
Region.SCROLL_BAR_TRACK);
paintTrack(subcontext, g, getTrackBounds());
- subcontext.dispose();
subcontext = getContext(scrollbar, Region.SCROLL_BAR_THUMB);
paintThumb(subcontext, g, getThumbBounds());
- subcontext.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -83,7 +83,6 @@
context.getPainter().paintScrollPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -100,7 +99,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -150,7 +148,6 @@
installKeyboardActions(c);
}
}
- context.dispose();
}
/**
@@ -178,7 +175,6 @@
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
if (scrollpane.getViewportBorder() instanceof UIResource) {
scrollpane.setViewportBorder(null);
@@ -254,7 +250,6 @@
}
context.getPainter().paintViewportBorder(context, g, x, y, width,
height);
- context.dispose();
}
@Override
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java Fri May 06 06:23:30 2016 -0700
@@ -106,7 +106,6 @@
}
}
- context.dispose();
}
/**
@@ -120,7 +119,6 @@
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -168,7 +166,6 @@
g, 0, 0, c.getWidth(), c.getHeight(),
separator.getOrientation());
paint(context, g);
- context.dispose();
}
/**
@@ -185,7 +182,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -231,7 +227,6 @@
size = new Dimension(insets.left + insets.right,
insets.top + insets.bottom + thickness);
}
- context.dispose();
return size;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java Fri May 06 06:23:30 2016 -0700
@@ -116,17 +116,14 @@
protected void uninstallDefaults(JSlider slider) {
SynthContext context = getContext(slider, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
context = getContext(slider, Region.SLIDER_TRACK, ENABLED);
sliderTrackStyle.uninstallDefaults(context);
- context.dispose();
sliderTrackStyle = null;
context = getContext(slider, Region.SLIDER_THUMB, ENABLED);
sliderThumbStyle.uninstallDefaults(context);
- context.dispose();
sliderThumbStyle = null;
}
@@ -190,17 +187,14 @@
installKeyboardActions(c);
}
}
- context.dispose();
context = getContext(c, Region.SLIDER_TRACK, ENABLED);
sliderTrackStyle =
SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
context = getContext(c, Region.SLIDER_THUMB, ENABLED);
sliderThumbStyle =
SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -252,14 +246,12 @@
SynthContext trackContext = getContext(slider,
Region.SLIDER_TRACK);
style.getInsets(trackContext, trackInsets);
- trackContext.dispose();
if (slider.getOrientation() == JSlider.HORIZONTAL) {
int valueHeight = 0;
if (paintValue) {
SynthContext context = getContext(slider);
valueHeight = context.getStyle().getGraphicsUtils(context).
getMaximumCharHeight(context);
- context.dispose();
}
int tickHeight = 0;
if (slider.getPaintTicks()) {
@@ -287,7 +279,6 @@
SynthContext context = getContext(slider);
valueHeight = context.getStyle().getGraphicsUtils(
context).getMaximumCharHeight(context);
- context.dispose();
}
int contentHeight = height - insetCache.top -
insetCache.bottom;
@@ -359,7 +350,6 @@
Insets trackInsets = new Insets(0, 0, 0, 0);
SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK);
style.getInsets(trackContext, trackInsets);
- trackContext.dispose();
if (slider.getOrientation() == JSlider.HORIZONTAL) {
// Calculate the height of all the subcomponents so we can center
@@ -509,7 +499,6 @@
trackRect.x = startX + tickRect.width + trackInsets.left;
}
}
- context.dispose();
lastSize = slider.getSize();
}
@@ -715,7 +704,6 @@
insetCache = newInsets;
calculateGeometry();
}
- context.dispose();
}
/**
@@ -774,7 +762,6 @@
g, 0, 0, c.getWidth(), c.getHeight(),
slider.getOrientation());
paint(context, g);
- context.dispose();
}
/**
@@ -790,7 +777,6 @@
public void paint(Graphics g, JComponent c) {
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -835,13 +821,11 @@
if (slider.getPaintTrack() && clip.intersects(trackRect)) {
SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK);
paintTrack(subcontext, g, trackRect);
- subcontext.dispose();
}
if (clip.intersects(thumbRect)) {
SynthContext subcontext = getContext(slider, Region.SLIDER_THUMB);
paintThumb(subcontext, g, thumbRect);
- subcontext.dispose();
}
if (slider.getPaintTicks() && clip.intersects(tickRect)) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java Fri May 06 06:23:30 2016 -0700
@@ -131,7 +131,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
@@ -151,7 +150,6 @@
SynthContext context = getContext(spinner, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -301,7 +299,6 @@
context.getPainter().paintSpinnerBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
@@ -319,7 +316,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java Fri May 06 06:23:30 2016 -0700
@@ -81,7 +81,6 @@
context.getPainter().paintSplitPaneDividerForeground(context, g, 0, 0,
getWidth(), getHeight(), splitPane.getOrientation());
- context.dispose();
// super.paint(g2);
for (int counter = 0; counter < getComponentCount(); counter++) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -121,7 +121,6 @@
ENABLED);
SynthStyle oldDividerStyle = dividerStyle;
dividerStyle = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
context = getContext(splitPane, ENABLED);
SynthStyle oldStyle = style;
@@ -160,7 +159,6 @@
divider.setBasicSplitPaneUI(this);
splitPane.add(divider, JSplitPane.DIVIDER);
}
- context.dispose();
}
/**
@@ -180,12 +178,10 @@
SynthContext context = getContext(splitPane, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER, ENABLED);
dividerStyle.uninstallDefaults(context);
- context.dispose();
dividerStyle = null;
super.uninstallDefaults();
@@ -287,7 +283,6 @@
context.getPainter().paintSplitPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -304,7 +299,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -338,7 +332,6 @@
context.getPainter().paintSplitPaneDragDivider(context, g, x, y, w, h,
splitPane.getOrientation());
g.setClip(oldClip);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java Fri May 06 06:23:30 2016 -0700
@@ -154,27 +154,17 @@
installKeyboardActions();
}
}
- context.dispose();
- if (tabContext != null) {
- tabContext.dispose();
- }
tabContext = getContext(c, Region.TABBED_PANE_TAB, ENABLED);
this.tabStyle = SynthLookAndFeel.updateStyle(tabContext, this);
tabInsets = tabStyle.getInsets(tabContext, null);
- if (tabAreaContext != null) {
- tabAreaContext.dispose();
- }
tabAreaContext = getContext(c, Region.TABBED_PANE_TAB_AREA, ENABLED);
this.tabAreaStyle = SynthLookAndFeel.updateStyle(tabAreaContext, this);
tabAreaInsets = tabAreaStyle.getInsets(tabAreaContext, null);
- if (tabContentContext != null) {
- tabContentContext.dispose();
- }
tabContentContext = getContext(c, Region.TABBED_PANE_CONTENT, ENABLED);
this.tabContentStyle = SynthLookAndFeel.updateStyle(tabContentContext,
this);
@@ -207,21 +197,17 @@
protected void uninstallDefaults() {
SynthContext context = getContext(tabPane, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
tabStyle.uninstallDefaults(tabContext);
- tabContext.dispose();
tabContext = null;
tabStyle = null;
tabAreaStyle.uninstallDefaults(tabAreaContext);
- tabAreaContext.dispose();
tabAreaContext = null;
tabAreaStyle = null;
tabContentStyle.uninstallDefaults(tabContentContext);
- tabContentContext.dispose();
tabContentContext = null;
tabContentStyle = null;
}
@@ -374,7 +360,6 @@
context.getPainter().paintTabbedPaneBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -424,7 +409,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java Fri May 06 06:23:30 2016 -0700
@@ -85,7 +85,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -109,7 +108,6 @@
SynthContext context = getContext(header, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -142,7 +140,6 @@
context.getPainter().paintTableHeaderBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -159,7 +156,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java Fri May 06 06:23:30 2016 -0700
@@ -189,7 +189,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -220,7 +219,6 @@
}
SynthContext context = getContext(table, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -273,7 +271,6 @@
context.getPainter().paintTableBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -299,7 +296,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java Fri May 06 06:23:30 2016 -0700
@@ -88,7 +88,6 @@
getComponent().removeFocusListener(handler);
style.uninstallDefaults(context);
- context.dispose();
style = null;
super.uninstallDefaults();
}
@@ -107,7 +106,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -142,7 +140,6 @@
context.getPainter().paintTextAreaBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java Fri May 06 06:23:30 2016 -0700
@@ -79,7 +79,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
static void updateStyle(JTextComponent comp, SynthContext context,
@@ -179,7 +178,6 @@
SynthLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
- context.dispose();
}
/**
@@ -262,7 +260,6 @@
getComponent().removeFocusListener(handler);
style.uninstallDefaults(context);
- context.dispose();
style = null;
super.uninstallDefaults();
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java Fri May 06 06:23:30 2016 -0700
@@ -98,11 +98,9 @@
SynthContext context = getContext(
c, Region.TOOL_BAR_CONTENT, null, ENABLED);
contentStyle = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
context = getContext(c, Region.TOOL_BAR_DRAG_WINDOW, null, ENABLED);
dragWindowStyle = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
@@ -116,7 +114,6 @@
installKeyboardActions();
}
}
- context.dispose();
}
/**
@@ -127,7 +124,6 @@
SynthContext context = getContext(toolBar, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
handleIcon = null;
@@ -135,13 +131,11 @@
context = getContext(toolBar, Region.TOOL_BAR_CONTENT,
contentStyle, ENABLED);
contentStyle.uninstallDefaults(context);
- context.dispose();
contentStyle = null;
context = getContext(toolBar, Region.TOOL_BAR_DRAG_WINDOW,
dragWindowStyle, ENABLED);
dragWindowStyle.uninstallDefaults(context);
- context.dispose();
dragWindowStyle = null;
toolBar.setLayout(null);
@@ -215,7 +209,6 @@
g, 0, 0, c.getWidth(), c.getHeight(),
toolBar.getOrientation());
paint(context, g);
- context.dispose();
}
/**
@@ -232,7 +225,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -289,7 +281,6 @@
SynthContext subcontext = getContext(
toolBar, Region.TOOL_BAR_CONTENT, contentStyle);
paintContent(subcontext, g, contentRect);
- subcontext.dispose();
}
/**
@@ -326,7 +317,6 @@
dragWindow.getOrientation());
context.getPainter().paintToolBarDragWindowBorder(context, g, 0, 0, w, h,
dragWindow.getOrientation());
- context.dispose();
}
//
@@ -383,7 +373,6 @@
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
- context.dispose();
return dim;
}
@@ -421,7 +410,6 @@
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
- context.dispose();
return dim;
}
@@ -543,7 +531,6 @@
}
}
}
- context.dispose();
}
private boolean isGlue(Component c) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java Fri May 06 06:23:30 2016 -0700
@@ -68,7 +68,6 @@
private void updateStyle(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -78,7 +77,6 @@
protected void uninstallDefaults(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -139,7 +137,6 @@
context.getPainter().paintToolTipBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -165,7 +162,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -218,7 +214,6 @@
prefSize.height += fm.getHeight();
}
}
- context.dispose();
return prefSize;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java Fri May 06 06:23:30 2016 -0700
@@ -147,11 +147,9 @@
installKeyboardActions();
}
}
- context.dispose();
context = getContext(tree, Region.TREE_CELL, ENABLED);
cellStyle = SynthLookAndFeel.updateStyle(context, this);
- context.dispose();
}
/**
@@ -223,12 +221,10 @@
SynthContext context = getContext(tree, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
context = getContext(tree, Region.TREE_CELL, ENABLED);
cellStyle.uninstallDefaults(context);
- context.dispose();
cellStyle = null;
@@ -266,7 +262,6 @@
context.getPainter().paintTreeBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -292,7 +287,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
@@ -425,7 +419,6 @@
row++;
}
}
- cellContext.dispose();
paintDropLine(g);
@@ -743,7 +736,6 @@
context.getPainter().paintTreeCellFocus(context, g,
0, 0, getWidth() - imageOffset, getHeight());
}
- context.dispose();
}
SynthLookAndFeel.resetSelectedUI();
}
@@ -785,7 +777,6 @@
if (context == null) {
context = getContext(tree);
SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
- context.dispose();
}
else {
SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
@@ -797,7 +788,6 @@
if (context == null) {
context = getContext(tree);
width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
- context.dispose();
}
else {
width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
@@ -810,7 +800,6 @@
if (context == null) {
context = getContext(tree);
height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
- context.dispose();
}
else {
height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java Fri May 06 06:23:30 2016 -0700
@@ -99,7 +99,6 @@
newStyle.installDefaults(context);
}
this.style = newStyle;
- context.dispose();
}
/**
@@ -128,7 +127,6 @@
protected void uninstallDefaults(JComponent c) {
SynthContext context = getContext(c, ENABLED);
style.uninstallDefaults(context);
- context.dispose();
style = null;
}
@@ -168,7 +166,6 @@
context.getPainter().paintViewportBackground(context,
g, 0, 0, c.getWidth(), c.getHeight());
paint(context, g);
- context.dispose();
}
/**
@@ -202,7 +199,6 @@
SynthContext context = getContext(c);
paint(context, g);
- context.dispose();
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java Fri May 06 06:23:30 2016 -0700
@@ -2580,7 +2580,7 @@
* @param e the DocumentEvent
*/
public void insertUpdate(DocumentEvent e) {
- final Integer pos = new Integer (e.getOffset());
+ final Integer pos = e.getOffset();
if (SwingUtilities.isEventDispatchThread()) {
firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
} else {
@@ -2602,7 +2602,7 @@
* @param e the DocumentEvent
*/
public void removeUpdate(DocumentEvent e) {
- final Integer pos = new Integer (e.getOffset());
+ final Integer pos = e.getOffset();
if (SwingUtilities.isEventDispatchThread()) {
firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
} else {
@@ -2624,7 +2624,7 @@
* @param e the DocumentEvent
*/
public void changedUpdate(DocumentEvent e) {
- final Integer pos = new Integer (e.getOffset());
+ final Integer pos = e.getOffset();
if (SwingUtilities.isEventDispatchThread()) {
firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
} else {
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java Fri May 06 06:23:30 2016 -0700
@@ -73,7 +73,7 @@
* type the value class represents. For example:
* <code>setValueClass(Integer.class)</code> will cause the resulting
* value to be created via
- * <code>new Integer(((Number)formatter.parseObject(string)).intValue())</code>.
+ * <code>Integer.valueOf(((Number)formatter.parseObject(string)).intValue())</code>.
* This is typically useful if you
* wish to set a min/max value as the various <code>Number</code>
* implementations are generally not comparable to each other. This is also
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java Fri May 06 06:23:30 2016 -0700
@@ -608,7 +608,7 @@
* @param i the value
*/
public static void setFirstLineIndent(MutableAttributeSet a, float i) {
- a.addAttribute(FirstLineIndent, new Float(i));
+ a.addAttribute(FirstLineIndent, Float.valueOf(i));
}
/**
@@ -632,7 +632,7 @@
* @param i the value
*/
public static void setRightIndent(MutableAttributeSet a, float i) {
- a.addAttribute(RightIndent, new Float(i));
+ a.addAttribute(RightIndent, Float.valueOf(i));
}
/**
@@ -656,7 +656,7 @@
* @param i the value
*/
public static void setLeftIndent(MutableAttributeSet a, float i) {
- a.addAttribute(LeftIndent, new Float(i));
+ a.addAttribute(LeftIndent, Float.valueOf(i));
}
/**
@@ -680,7 +680,7 @@
* @param i the value
*/
public static void setLineSpacing(MutableAttributeSet a, float i) {
- a.addAttribute(LineSpacing, new Float(i));
+ a.addAttribute(LineSpacing, Float.valueOf(i));
}
/**
@@ -704,7 +704,7 @@
* @param i the value
*/
public static void setSpaceAbove(MutableAttributeSet a, float i) {
- a.addAttribute(SpaceAbove, new Float(i));
+ a.addAttribute(SpaceAbove, Float.valueOf(i));
}
/**
@@ -728,7 +728,7 @@
* @param i the value
*/
public static void setSpaceBelow(MutableAttributeSet a, float i) {
- a.addAttribute(SpaceBelow, new Float(i));
+ a.addAttribute(SpaceBelow, Float.valueOf(i));
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java Fri May 06 06:23:30 2016 -0700
@@ -2564,7 +2564,7 @@
* represents the CSS attribute value
*/
Object toStyleConstants(StyleConstants key, View v) {
- return new Float(getValue(false));
+ return Float.valueOf(getValue(false));
}
/** If true, span is a percentage value, and that to determine
@@ -2837,25 +2837,25 @@
static Hashtable<String, Float> lengthMapping = new Hashtable<String, Float>(6);
static Hashtable<String, Float> w3cLengthMapping = new Hashtable<String, Float>(6);
static {
- lengthMapping.put("pt", new Float(1f));
+ lengthMapping.put("pt", Float.valueOf(1f));
// Not sure about 1.3, determined by experiementation.
- lengthMapping.put("px", new Float(1.3f));
- lengthMapping.put("mm", new Float(2.83464f));
- lengthMapping.put("cm", new Float(28.3464f));
- lengthMapping.put("pc", new Float(12f));
- lengthMapping.put("in", new Float(72f));
+ lengthMapping.put("px", Float.valueOf(1.3f));
+ lengthMapping.put("mm", Float.valueOf(2.83464f));
+ lengthMapping.put("cm", Float.valueOf(28.3464f));
+ lengthMapping.put("pc", Float.valueOf(12f));
+ lengthMapping.put("in", Float.valueOf(72f));
int res = 72;
try {
res = Toolkit.getDefaultToolkit().getScreenResolution();
} catch (HeadlessException e) {
}
// mapping according to the CSS2 spec
- w3cLengthMapping.put("pt", new Float(res/72f));
- w3cLengthMapping.put("px", new Float(1f));
- w3cLengthMapping.put("mm", new Float(res/25.4f));
- w3cLengthMapping.put("cm", new Float(res/2.54f));
- w3cLengthMapping.put("pc", new Float(res/6f));
- w3cLengthMapping.put("in", new Float(res));
+ w3cLengthMapping.put("pt", Float.valueOf(res/72f));
+ w3cLengthMapping.put("px", Float.valueOf(1f));
+ w3cLengthMapping.put("mm", Float.valueOf(res/25.4f));
+ w3cLengthMapping.put("cm", Float.valueOf(res/2.54f));
+ w3cLengthMapping.put("pc", Float.valueOf(res/6f));
+ w3cLengthMapping.put("in", Float.valueOf((float)res));
}
LengthUnit(String value, short defaultType, float defaultValue) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java Fri May 06 06:23:30 2016 -0700
@@ -357,7 +357,7 @@
public static NumericAttribute NewTwips(int d, Object s, String r,
float ds, int dr)
{
- return new NumericAttribute(d, s, r, new Float(ds), dr, 20f);
+ return new NumericAttribute(d, s, r, Float.valueOf(ds), dr, 20f);
}
public static NumericAttribute NewTwips(int d, Object s, String r,
@@ -378,7 +378,7 @@
if (scale == 1f)
swingValue = Integer.valueOf(parameter);
else
- swingValue = new Float(parameter / scale);
+ swingValue = Float.valueOf(parameter / scale);
target.addAttribute(swingName, swingValue);
return true;
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, 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
@@ -29,6 +29,7 @@
import javax.accessibility.AccessibleContext;
import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.peer.DragSourceContextPeer;
@@ -104,7 +105,7 @@
/*
* Requests focus to the component.
*/
- boolean requestFocus(Component comp, CausedFocusEvent.Cause cause);
+ boolean requestFocus(Component comp, Cause cause);
/*
* Determines if the component can gain focus.
*/
@@ -438,7 +439,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause);
+ Cause cause);
/**
* Delivers focus for the lightweight descendant of the heavyweight
* synchronously.
--- a/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -27,17 +27,18 @@
import java.awt.event.FocusEvent;
import java.awt.Component;
+import java.io.ObjectStreamException;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
/**
- * This class represents FocusEvents with a known "cause" - reason why this event happened. It can
- * be mouse press, traversal, activation, and so on - all causes are described as Cause enum. The
- * event with the cause can be constructed in two ways - explicitly through constructor of
- * CausedFocusEvent class or implicitly, by calling appropriate requestFocusXXX method with "cause"
- * parameter. The default cause is UNKNOWN.
+ * This class exists for deserialization compatibility only.
*/
-@SuppressWarnings("serial")
-public class CausedFocusEvent extends FocusEvent {
- public enum Cause {
+class CausedFocusEvent extends FocusEvent {
+ private static final long serialVersionUID = -3647309088427840738L;
+
+ private enum Cause {
UNKNOWN,
MOUSE_EVENT,
TRAVERSAL,
@@ -51,39 +52,82 @@
NATIVE_SYSTEM,
ACTIVATION,
CLEAR_GLOBAL_FOCUS_OWNER,
- RETARGETED
+ RETARGETED;
};
+ @SuppressWarnings("serial")
+ private static final Component dummy = new Component(){};
+
private final Cause cause;
- public Cause getCause() {
- return cause;
- }
-
- public String toString() {
- return "java.awt.FocusEvent[" + super.paramString() + ",cause=" + cause + "] on " + getSource();
- }
-
- public CausedFocusEvent(Component source, int id, boolean temporary,
+ private CausedFocusEvent(Component source, int id, boolean temporary,
Component opposite, Cause cause) {
super(source, id, temporary, opposite);
- if (cause == null) {
- cause = Cause.UNKNOWN;
- }
- this.cause = cause;
+ throw new IllegalStateException();
}
- /**
- * Retargets the original focus event to the new target. If the
- * original focus event is CausedFocusEvent, it remains such and
- * cause is copied. Otherwise, new CausedFocusEvent is created,
- * with cause as RETARGETED.
- * @return retargeted event, or null if e is null
- */
- public static FocusEvent retarget(FocusEvent e, Component newSource) {
- if (e == null) return null;
+ Object readResolve() throws ObjectStreamException {
+ FocusEvent.Cause newCause;
+ switch (cause) {
+ case UNKNOWN:
+ newCause = FocusEvent.Cause.UNKNOWN;
+ break;
+ case MOUSE_EVENT:
+ newCause = FocusEvent.Cause.MOUSE_EVENT;
+ break;
+ case TRAVERSAL:
+ newCause = FocusEvent.Cause.TRAVERSAL;
+ break;
+ case TRAVERSAL_UP:
+ newCause = FocusEvent.Cause.TRAVERSAL_UP;
+ break;
+ case TRAVERSAL_DOWN:
+ newCause = FocusEvent.Cause.TRAVERSAL_DOWN;
+ break;
+ case TRAVERSAL_FORWARD:
+ newCause = FocusEvent.Cause.TRAVERSAL_FORWARD;
+ break;
+ case TRAVERSAL_BACKWARD:
+ newCause = FocusEvent.Cause.TRAVERSAL_BACKWARD;
+ break;
+ case ROLLBACK:
+ newCause = FocusEvent.Cause.ROLLBACK;
+ break;
+ case NATIVE_SYSTEM:
+ newCause = FocusEvent.Cause.UNEXPECTED;
+ break;
+ case ACTIVATION:
+ newCause = FocusEvent.Cause.ACTIVATION;
+ break;
+ case CLEAR_GLOBAL_FOCUS_OWNER:
+ newCause = FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER;
+ break;
+ default:
+ newCause = FocusEvent.Cause.UNKNOWN;
+ }
- return new CausedFocusEvent(newSource, e.getID(), e.isTemporary(), e.getOppositeComponent(),
- (e instanceof CausedFocusEvent) ? ((CausedFocusEvent)e).getCause() : Cause.RETARGETED);
+ FocusEvent focusEvent = new FocusEvent(dummy, getID(), isTemporary(),
+ getOppositeComponent(), newCause);
+ focusEvent.setSource(null);
+ try {
+ final Field consumedField = FocusEvent.class.getField("consumed");
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ consumedField.setAccessible(true);
+ try {
+ consumedField.set(focusEvent, consumed);
+ } catch (IllegalAccessException e) {
+ }
+ return null;
+ }
+ });
+ } catch (NoSuchFieldException e) {
+ }
+
+ AWTAccessor.AWTEventAccessor accessor =
+ AWTAccessor.getAWTEventAccessor();
+ accessor.setBData(focusEvent, accessor.getBData(this));
+ return focusEvent;
}
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,8 +60,8 @@
focusLog.fine("Clearing global focus owner " + focusOwner);
}
if (focusOwner != null) {
- FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
- CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
+ FocusEvent fl = new FocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
+ FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
SunToolkit.postPriorityEvent(fl);
}
}
@@ -110,7 +110,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause,
+ FocusEvent.Cause cause,
Component currentFocusOwner) // provided by the descendant peers
{
if (lightweightChild == null) {
@@ -122,7 +122,7 @@
currentOwner = null;
}
if (currentOwner != null) {
- FocusEvent fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
+ FocusEvent fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
false, lightweightChild, cause);
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
@@ -131,7 +131,7 @@
SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
}
- FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
+ FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
false, currentOwner, cause);
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
@@ -142,7 +142,7 @@
}
// WARNING: Don't call it on the Toolkit thread.
- public static boolean requestFocusFor(Component target, CausedFocusEvent.Cause cause) {
+ public static boolean requestFocusFor(Component target, FocusEvent.Cause cause) {
return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
}
@@ -152,7 +152,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
return KfmAccessor.instance.shouldNativelyFocusHeavyweight(
heavyweight, descendant, temporary, focusedWindowChangeAllowed,
--- a/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Insets;
-import java.awt.MenuBar;
+import java.awt.event.FocusEvent.Cause;
import java.awt.Point;
import java.awt.Event;
import java.awt.event.PaintEvent;
@@ -178,7 +178,7 @@
public boolean requestFocus
(Component lightweightChild, boolean temporary,
- boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) {
+ boolean focusedWindowChangeAllowed, long time, Cause cause) {
return false;
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,11 @@
package sun.awt;
import java.awt.Component;
+import java.awt.event.FocusEvent.Cause;
public interface RequestFocusController
{
public boolean acceptRequestFocus(Component from, Component to,
boolean temporary, boolean focusedWindowChangeAllowed,
- CausedFocusEvent.Cause cause);
+ Cause cause);
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java Fri May 06 06:23:30 2016 -0700
@@ -87,7 +87,7 @@
properties.put(key,value);
}
private void property(String key,float value) {
- property(key,new Float(value));
+ property(key, Float.valueOf(value));
}
private final void pngassert(boolean b) throws IOException {
if(!b) {
--- a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java Fri May 06 06:23:30 2016 -0700
@@ -1843,7 +1843,7 @@
private PhysicalFont registerFontFile(String file) {
if (new File(file).isAbsolute() &&
- !registeredFonts.contains(file)) {
+ !registeredFonts.containsKey(file)) {
int fontFormat = FONTFORMAT_NONE;
int fontRank = Font2D.UNKNOWN_RANK;
if (ttFilter.accept(null, file)) {
--- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Fri May 06 06:23:30 2016 -0700
@@ -1388,6 +1388,8 @@
Doc doc = new PageableDoc(getPageable());
if (attributes == null) {
attributes = new HashPrintRequestAttributeSet();
+ attributes.add(new Copies(getCopies()));
+ attributes.add(new JobName(getJobName(), null));
}
try {
job.print(doc, attributes);
--- a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java Fri May 06 06:23:30 2016 -0700
@@ -1402,8 +1402,8 @@
format.setParseIntegerOnly(false);
format.setDecimalSeparatorAlwaysShown(true);
NumberFormatter nf = new NumberFormatter(format);
- nf.setMinimum(new Float(0.0f));
- nf.setMaximum(new Float(999.0f));
+ nf.setMinimum(Float.valueOf(0.0f));
+ nf.setMaximum(Float.valueOf(999.0f));
nf.setAllowsInvalid(true);
nf.setCommitsOnValidEdit(true);
@@ -1422,13 +1422,13 @@
topMargin.addActionListener(this);
topMargin.getAccessibleContext().setAccessibleName(
getMsg("label.topmargin"));
- topMargin = new JFormattedTextField(nf);
+
bottomMargin = new JFormattedTextField(nf);
bottomMargin.addFocusListener(this);
bottomMargin.addActionListener(this);
bottomMargin.getAccessibleContext().setAccessibleName(
getMsg("label.bottommargin"));
- topMargin = new JFormattedTextField(nf);
+
c.gridwidth = GridBagConstraints.RELATIVE;
lblLeft = new JLabel(getMsg("label.leftmargin") + " " + unitsMsg,
JLabel.LEADING);
@@ -1836,10 +1836,10 @@
rmVal = mediaSize.getX(units) - pax - paw;
bmVal = mediaSize.getY(units) - pay - pah;
- lmObj = new Float(lmVal);
- rmObj = new Float(rmVal);
- tmObj = new Float(tmVal);
- bmObj = new Float(bmVal);
+ lmObj = lmVal;
+ rmObj = rmVal;
+ tmObj = tmVal;
+ bmObj = bmVal;
/* Now we know the values to use, we need to assign them
* to the fields appropriate for the orientation.
--- a/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package sun.swing;
+import javax.swing.UIClientPropertyKey;
+
/**
* An implementation of {@code UIClientPropertyKey} that wraps a {@code String}.
*
--- a/jdk/src/java.desktop/share/classes/sun/swing/UIClientPropertyKey.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.swing;
-
-/**
- * This interface is used only for tagging keys for client properties
- * for {@code JComponent} set by UI which needs to be cleared on {@literal L&F}
- * change and serialization.
- *
- * All such keys are removed from client properties in {@code
- * JComponent.setUI()} method after uninstalling old UI and before
- * intalling the new one. They are also removed prior to serialization.
- *
- * @author Igor Kushnirskiy
- */
-public interface UIClientPropertyKey {
-}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,12 @@
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import sun.security.action.GetIntegerAction;
import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;
import sun.java2d.opengl.OGLRenderQueue;
+import sun.security.action.GetPropertyAction;
public abstract class UNIXToolkit extends SunToolkit
{
@@ -42,6 +45,40 @@
private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 };
private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000;
+ // Allowed GTK versions
+ public enum GtkVersions {
+ ANY(0),
+ GTK2(Constants.GTK2_MAJOR_NUMBER),
+ GTK3(Constants.GTK3_MAJOR_NUMBER);
+
+ static class Constants {
+ static final int GTK2_MAJOR_NUMBER = 2;
+ static final int GTK3_MAJOR_NUMBER = 3;
+ }
+
+ final int number;
+
+ GtkVersions(int number) {
+ this.number = number;
+ }
+
+ public static GtkVersions getVersion(int number) {
+ switch (number) {
+ case Constants.GTK2_MAJOR_NUMBER:
+ return GTK2;
+ case Constants.GTK3_MAJOR_NUMBER:
+ return GTK3;
+ default:
+ return ANY;
+ }
+ }
+
+ // major GTK version number
+ public int getNumber() {
+ return number;
+ }
+ };
+
private Boolean nativeGTKAvailable;
private Boolean nativeGTKLoaded;
private BufferedImage tmpImage = null;
@@ -79,7 +116,7 @@
return nativeGTKAvailable;
} else {
- boolean success = check_gtk();
+ boolean success = check_gtk(getEnabledGtkVersion().getNumber());
nativeGTKAvailable = success;
return success;
}
@@ -97,7 +134,8 @@
public boolean loadGTK() {
synchronized (GTK_LOCK) {
if (nativeGTKLoaded == null) {
- nativeGTKLoaded = load_gtk();
+ nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(),
+ isGtkVerbose());
}
}
return nativeGTKLoaded;
@@ -241,14 +279,15 @@
tmpImage = new BufferedImage(colorModel, raster, false, null);
}
- private static native boolean check_gtk();
- private static native boolean load_gtk();
+ private static native boolean check_gtk(int version);
+ private static native boolean load_gtk(int version, boolean verbose);
private static native boolean unload_gtk();
private native boolean load_gtk_icon(String filename);
private native boolean load_stock_icon(int widget_type, String stock_id,
int iconSize, int textDirection, String detail);
private native void nativeSync();
+ private static native int get_gtk_version();
@Override
public void sync() {
@@ -338,4 +377,26 @@
}
return false;
}
+
+ public static GtkVersions getEnabledGtkVersion() {
+ String version = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.gtk.version"));
+ if (version == null) {
+ return GtkVersions.ANY;
+ } else if (version.startsWith("2")) {
+ return GtkVersions.GTK2;
+ } else if("3".equals(version) ){
+ return GtkVersions.GTK3;
+ }
+ return GtkVersions.ANY;
+ }
+
+ public static GtkVersions getGtkVersion() {
+ return GtkVersions.getVersion(get_gtk_version());
+ }
+
+ public static boolean isGtkVerbose() {
+ return AccessController.doPrivileged((PrivilegedAction<Boolean>)()
+ -> Boolean.getBoolean("jdk.gtk.verbose"));
+ }
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, 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
@@ -287,7 +287,7 @@
@SuppressWarnings("deprecation")
public final boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
if (XKeyboardFocusManagerPeer.
processSynchronousLightweightTransfer(target, lightweightChild, temporary,
@@ -527,7 +527,7 @@
// WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
// parentWindow.dispatchEvent(wfg);
// }
- XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
+ XKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
}
break;
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -26,6 +26,8 @@
package sun.awt.X11;
+import sun.awt.UNIXToolkit;
+
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -57,7 +59,8 @@
XToolkit.awtLock();
try {
if (!initExecuted) {
- nativeLibraryLoaded = init();
+ nativeLibraryLoaded = init(UNIXToolkit.getEnabledGtkVersion()
+ .ordinal(), UNIXToolkit.isGtkVerbose());
}
} finally {
initExecuted = true;
@@ -123,5 +126,5 @@
}
private native boolean gnome_url_show(byte[] url);
- private static native boolean init();
+ private static native boolean init(int gtkVersion, boolean verbose);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -430,13 +430,10 @@
if (isXEmbedActive()) {
xembedLog.fine("Forwarding FOCUS_GAINED");
int flavor = XEMBED_FOCUS_CURRENT;
- if (e instanceof CausedFocusEvent) {
- CausedFocusEvent ce = (CausedFocusEvent)e;
- if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) {
- flavor = XEMBED_FOCUS_FIRST;
- } else if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) {
- flavor = XEMBED_FOCUS_LAST;
- }
+ if (e.getCause() == FocusEvent.Cause.TRAVERSAL_FORWARD) {
+ flavor = XEMBED_FOCUS_FIRST;
+ } else if (e.getCause() == FocusEvent.Cause.TRAVERSAL_BACKWARD) {
+ flavor = XEMBED_FOCUS_LAST;
}
xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN, flavor, 0, 0);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -195,7 +195,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
int result = XKeyboardFocusManagerPeer
.shouldNativelyFocusHeavyweight(proxy, lightweightChild,
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, 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
@@ -28,7 +28,7 @@
import java.awt.Window;
import sun.awt.AWTAccessor;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent;
import sun.awt.KeyboardFocusManagerPeerImpl;
import sun.util.logging.PlatformLogger;
@@ -101,7 +101,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
target,
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java Fri May 06 06:23:30 2016 -0700
@@ -29,6 +29,8 @@
import java.awt.Taskbar.Feature;
import java.awt.peer.TaskbarPeer;
import java.awt.event.ActionEvent;
+
+import sun.awt.UNIXToolkit;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
@@ -45,7 +47,9 @@
if (!initExecuted) {
String dname = AccessController.doPrivileged(
new GetPropertyAction("java.desktop.appName", ""));
- nativeLibraryLoaded = init(dname);
+ nativeLibraryLoaded = init(dname,
+ UNIXToolkit.getEnabledGtkVersion().ordinal(),
+ UNIXToolkit.isGtkVerbose());
if (nativeLibraryLoaded) {
Thread t = new Thread(null, () -> { runloop(); },
"TaskBar", 0, false);
@@ -147,7 +151,8 @@
}
}
- private static native boolean init(String name);
+ private static native boolean init(String name, int version,
+ boolean verbose);
private static native void runloop();
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,6 @@
import javax.swing.plaf.BorderUIResource;
import java.awt.im.InputMethodRequests;
-import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
import sun.awt.SunToolkit;
@@ -945,14 +944,16 @@
void forwardFocusGained( FocusEvent e) {
isFocused = true;
- FocusEvent fe = CausedFocusEvent.retarget(e, this);
+ FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+ e.getOppositeComponent(), e.getCause());
super.processFocusEvent(fe);
}
void forwardFocusLost( FocusEvent e) {
isFocused = false;
- FocusEvent fe = CausedFocusEvent.retarget(e, this);
+ FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+ e.getOppositeComponent(), e.getCause());
super.processFocusEvent(fe);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,6 @@
import sun.util.logging.PlatformLogger;
-import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
final class XTextFieldPeer extends XComponentPeer implements TextFieldPeer {
@@ -618,13 +617,15 @@
void forwardFocusGained( FocusEvent e) {
isFocused = true;
- FocusEvent fe = CausedFocusEvent.retarget(e, this);
+ FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+ e.getOppositeComponent(), e.getCause());
super.processFocusEvent(fe);
}
void forwardFocusLost( FocusEvent e) {
isFocused = false;
- FocusEvent fe = CausedFocusEvent.retarget(e, this);
+ FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+ e.getOppositeComponent(), e.getCause());
super.processFocusEvent(fe);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Fri May 06 06:23:30 2016 -0700
@@ -1143,7 +1143,8 @@
public FileDialogPeer createFileDialog(FileDialog target) {
FileDialogPeer peer = null;
// The current GtkFileChooser is available from GTK+ 2.4
- if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) {
+ if (!getSunAwtDisableGtkFileDialogs() &&
+ (checkGtkVersion(2, 4, 0) || checkGtkVersion(3, 0, 0))) {
peer = new GtkFileDialogPeer(target);
} else {
peer = new XFileDialogPeer(target);
--- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java Fri May 06 06:23:30 2016 -0700
@@ -117,7 +117,7 @@
if (refreshTimeStr != null) {
try {
- minRefreshTime = (new Integer(refreshTimeStr)).intValue();
+ minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
} catch (NumberFormatException e) {
}
if (minRefreshTime < DEFAULT_MINREFRESH) {
--- a/jdk/src/java.desktop/unix/native/common/awt/awt.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/common/awt/awt.h Fri May 06 06:23:30 2016 -0700
@@ -35,7 +35,9 @@
#include "debug_util.h"
#if !defined(HEADLESS) && !defined(MACOSX)
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+typedef char Boolean;
#endif /* !HEADLESS && !MACOSX */
--- a/jdk/src/java.desktop/unix/native/common/awt/awt_p.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/common/awt/awt_p.h Fri May 06 06:23:30 2016 -0700
@@ -41,13 +41,6 @@
#include <string.h>
#include <unistd.h>
#ifndef HEADLESS
-#include <X11/Intrinsic.h>
-#include <X11/IntrinsicP.h>
-#include <X11/Shell.h>
-#include <X11/StringDefs.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/keysymdef.h>
#include <X11/extensions/Xrender.h>
#endif /* !HEADLESS */
#include "awt.h"
--- a/jdk/src/java.desktop/unix/native/common/awt/extutil.h Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * $Xorg: extutil.h,v 1.3 2000/08/18 04:05:45 coskrey Exp $
- *
-Copyright 1989, 1998 The Open Group
-
-All Rights Reserved.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author: Jim Fulton, MIT The Open Group
- *
- * Xlib Extension-Writing Utilities
- *
- * This package contains utilities for writing the client API for various
- * protocol extensions. THESE INTERFACES ARE NOT PART OF THE X STANDARD AND
- * ARE SUBJECT TO CHANGE!
- */
-/* $XFree86: xc/include/extensions/extutil.h,v 1.5 2001/01/17 17:53:20 dawes Exp $ */
-
-#if defined(__linux__) || defined(MACOSX)
-
-#ifndef _EXTUTIL_H_
-#define _EXTUTIL_H_
-
-/*
- * We need to keep a list of open displays since the Xlib display list isn't
- * public. We also have to per-display info in a separate block since it isn't
- * stored directly in the Display structure.
- */
-typedef struct _XExtDisplayInfo {
- struct _XExtDisplayInfo *next; /* keep a linked list */
- Display *display; /* which display this is */
- XExtCodes *codes; /* the extension protocol codes */
- XPointer data; /* extra data for extension to use */
-} XExtDisplayInfo;
-
-typedef struct _XExtensionInfo {
- XExtDisplayInfo *head; /* start of list */
- XExtDisplayInfo *cur; /* most recently used */
- int ndisplays; /* number of displays */
-} XExtensionInfo;
-
-typedef struct _XExtensionHooks {
- int (*create_gc)(
-#if NeedNestedPrototypes
- Display* /* display */,
- GC /* gc */,
- XExtCodes* /* codes */
-#endif
-);
- int (*copy_gc)(
-#if NeedNestedPrototypes
- Display* /* display */,
- GC /* gc */,
- XExtCodes* /* codes */
-#endif
-);
- int (*flush_gc)(
-#if NeedNestedPrototypes
- Display* /* display */,
- GC /* gc */,
- XExtCodes* /* codes */
-#endif
-);
- int (*free_gc)(
-#if NeedNestedPrototypes
- Display* /* display */,
- GC /* gc */,
- XExtCodes* /* codes */
-#endif
-);
- int (*create_font)(
-#if NeedNestedPrototypes
- Display* /* display */,
- XFontStruct* /* fs */,
- XExtCodes* /* codes */
-#endif
-);
- int (*free_font)(
-#if NeedNestedPrototypes
- Display* /* display */,
- XFontStruct* /* fs */,
- XExtCodes* /* codes */
-#endif
-);
- int (*close_display)(
-#if NeedNestedPrototypes
- Display* /* display */,
- XExtCodes* /* codes */
-#endif
-);
- Bool (*wire_to_event)(
-#if NeedNestedPrototypes
- Display* /* display */,
- XEvent* /* re */,
- xEvent* /* event */
-#endif
-);
- Status (*event_to_wire)(
-#if NeedNestedPrototypes
- Display* /* display */,
- XEvent* /* re */,
- xEvent* /* event */
-#endif
-);
- int (*error)(
-#if NeedNestedPrototypes
- Display* /* display */,
- xError* /* err */,
- XExtCodes* /* codes */,
- int* /* ret_code */
-#endif
-);
- char *(*error_string)(
-#if NeedNestedPrototypes
- Display* /* display */,
- int /* code */,
- XExtCodes* /* codes */,
- char* /* buffer */,
- int /* nbytes */
-#endif
-);
-} XExtensionHooks;
-
-extern XExtensionInfo *XextCreateExtension(
-#if NeedFunctionPrototypes
- void
-#endif
-);
-extern void XextDestroyExtension(
-#if NeedFunctionPrototypes
- XExtensionInfo* /* info */
-#endif
-);
-extern XExtDisplayInfo *XextAddDisplay(
-#if NeedFunctionPrototypes
- XExtensionInfo* /* extinfo */,
- Display* /* dpy */,
- char* /* ext_name */,
- XExtensionHooks* /* hooks */,
- int /* nevents */,
- XPointer /* data */
-#endif
-);
-extern int XextRemoveDisplay(
-#if NeedFunctionPrototypes
- XExtensionInfo* /* extinfo */,
- Display* /* dpy */
-#endif
-);
-extern XExtDisplayInfo *XextFindDisplay(
-#if NeedFunctionPrototypes
- XExtensionInfo* /* extinfo */,
- Display* /* dpy */
-#endif
-);
-
-#define XextHasExtension(i) ((i) && ((i)->codes))
-#define XextCheckExtension(dpy,i,name,val) \
- if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return val; }
-#define XextSimpleCheckExtension(dpy,i,name) \
- if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return; }
-
-
-/*
- * helper macros to generate code that is common to all extensions; caller
- * should prefix it with static if extension source is in one file; this
- * could be a utility function, but have to stack 6 unused arguments for
- * something that is called many, many times would be bad.
- */
-#define XEXT_GENERATE_FIND_DISPLAY(proc,extinfo,extname,hooks,nev,data) \
-XExtDisplayInfo *proc (Display *dpy) \
-{ \
- XExtDisplayInfo *dpyinfo; \
- if (!extinfo) { if (!(extinfo = XextCreateExtension())) return NULL; } \
- if (!(dpyinfo = XextFindDisplay (extinfo, dpy))) \
- dpyinfo = XextAddDisplay (extinfo,dpy,extname,hooks,nev,data); \
- return dpyinfo; \
-}
-
-#define XEXT_FIND_DISPLAY_PROTO(proc) \
- XExtDisplayInfo *proc(Display *dpy)
-
-#define XEXT_GENERATE_CLOSE_DISPLAY(proc,extinfo) \
-int proc (Display *dpy, XExtCodes *codes) \
-{ \
- return XextRemoveDisplay (extinfo, dpy); \
-}
-
-#define XEXT_CLOSE_DISPLAY_PROTO(proc) \
- int proc(Display *dpy, XExtCodes *codes)
-
-#define XEXT_GENERATE_ERROR_STRING(proc,extname,nerr,errl) \
-char *proc (Display *dpy, int code, XExtCodes *codes, char *buf, int n) \
-{ \
- code -= codes->first_error; \
- if (code >= 0 && code < nerr) { \
- char tmp[256]; \
- sprintf (tmp, "%s.%d", extname, code); \
- XGetErrorDatabaseText (dpy, "XProtoError", tmp, errl[code], buf, n); \
- return buf; \
- } \
- return (char *)0; \
-}
-
-#define XEXT_ERROR_STRING_PROTO(proc) \
- char *proc(Display *dpy, int code, XExtCodes *codes, char *buf, int n)
-#endif
-
-#endif /* __linux__ || MACOSX */
--- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c Fri May 06 06:23:30 2016 -0700
@@ -270,7 +270,6 @@
xsdo->sdOps.Dispose = X11SD_Dispose;
xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg;
xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg;
- xsdo->widget = NULL;
if (peer != NULL) {
xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j;
if (hasException) {
@@ -1087,7 +1086,7 @@
X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
X11SDOps *xsdo)
{
- Position x1=0, y1=0, x2=0, y2=0;
+ short x1=0, y1=0, x2=0, y2=0;
int tmpx, tmpy;
Window tmpchild;
--- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h Fri May 06 06:23:30 2016 -0700
@@ -101,7 +101,6 @@
jboolean isPixmap;
jobject peer;
Drawable drawable;
- Widget widget;
GC javaGC; /* used for Java-level GC validation */
GC cachedGC; /* cached for use in X11SD_Unlock() */
jint depth;
--- a/jdk/src/java.desktop/unix/native/include/jawt_md.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/include/jawt_md.h Fri May 06 06:23:30 2016 -0700
@@ -28,7 +28,6 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <X11/Intrinsic.h>
#include "jawt.h"
#ifdef __cplusplus
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.
- */
-
-#ifndef HEADLESS
-
-#include <X11/IntrinsicP.h>
-#include "VDrawingAreaP.h"
-
-#endif /* !HEADLESS */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef __linux__
-/* XXX: Shouldn't be necessary. */
-#include "awt_p.h"
-#endif /* __linux__ */
-
-
-/******************************************************************
- *
- * Provides Canvas widget which allows the X11 visual to be
- * changed (the Motif DrawingArea restricts the visual to that
- * of the parent widget).
- *
- ******************************************************************/
-
-
-/******************************************************************
- *
- * VDrawingArea Widget Resources
- *
- ******************************************************************/
-
-#ifndef HEADLESS
-#define Offset(x) (XtOffsetOf(VDrawingAreaRec, x))
-static XtResource resources[]=
-{
- { XtNvisual, XtCVisual, XtRVisual, sizeof(Visual*),
- Offset(vdrawing_area.visual), XtRImmediate, CopyFromParent}
-};
-
-
-static void Realize();
-static Boolean SetValues();
-static void Destroy ();
-
-static XmBaseClassExtRec baseClassExtRec = {
- NULL,
- NULLQUARK,
- XmBaseClassExtVersion,
- sizeof(XmBaseClassExtRec),
- NULL, /* InitializePrehook */
- NULL, /* SetValuesPrehook */
- NULL, /* InitializePosthook */
- NULL, /* SetValuesPosthook */
- NULL, /* secondaryObjectClass */
- NULL, /* secondaryCreate */
- NULL, /* getSecRes data */
- { 0 }, /* fastSubclass flags */
- NULL, /* getValuesPrehook */
- NULL, /* getValuesPosthook */
- NULL, /* classPartInitPrehook */
- NULL, /* classPartInitPosthook*/
- NULL, /* ext_resources */
- NULL, /* compiled_ext_resources*/
- 0, /* num_ext_resources */
- FALSE, /* use_sub_resources */
- NULL, /* widgetNavigable */
- NULL, /* focusChange */
- NULL /* wrapper_data */
-};
-
-VDrawingAreaClassRec vDrawingAreaClassRec = {
-{
- /* Core class part */
-
- /* superclass */ (WidgetClass)&xmDrawingAreaClassRec,
- /* class_name */ "VDrawingArea",
- /* widget_size */ sizeof(VDrawingAreaRec),
- /* class_initialize */ NULL,
- /* class_part_initialize*/ NULL,
- /* class_inited */ FALSE,
- /* initialize */ NULL,
- /* initialize_hook */ NULL,
- /* realize */ Realize,
- /* actions */ NULL,
- /* num_actions */ 0,
- /* resources */ resources,
- /* num_resources */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ FALSE,
- /* compress_exposure */ FALSE,
- /* compress_enterleave*/ FALSE,
- /* visible_interest */ FALSE,
- /* destroy */ Destroy,
- /* resize */ XtInheritResize,
- /* expose */ XtInheritExpose,
- /* set_values */ SetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersion,
- /* callback_offsets */ NULL,
- /* tm_table */ NULL,
- /* query_geometry */ NULL,
- /* display_accelerator */ NULL,
- /* extension */ NULL
- },
-
- { /* composite_class fields */
- XtInheritGeometryManager, /* geometry_manager */
- XtInheritChangeManaged, /* change_managed */
- XtInheritInsertChild, /* insert_child */
- XtInheritDeleteChild, /* delete_child */
- NULL, /* extension */
- },
-
- { /* constraint_class fields */
- NULL, /* resource list */
- 0, /* num resources */
- 0, /* constraint size */
- NULL, /* init proc */
- NULL, /* destroy proc */
- NULL, /* set values proc */
- NULL, /* extension */
- },
-
- { /* manager_class fields */
- XtInheritTranslations, /* translations */
- NULL, /* syn_resources */
- 0, /* num_get_resources */
- NULL, /* syn_cont_resources */
- 0, /* num_get_cont_resources */
- XmInheritParentProcess, /* parent_process */
- NULL, /* extension */
- },
-
- { /* drawingArea class */
- /* extension */ NULL
- },
-
- /* VDrawingArea class part */
- {
- /* extension */ NULL
- }
-};
-
-WidgetClass vDrawingAreaClass = (WidgetClass)&vDrawingAreaClassRec;
-
-static Boolean
-SetValues(cw, rw, nw, args, num_args)
- Widget cw;
- Widget rw;
- Widget nw;
- ArgList args;
- Cardinal *num_args;
-{
- VDrawingAreaWidget current = (VDrawingAreaWidget)cw;
- VDrawingAreaWidget new_w = (VDrawingAreaWidget)nw;
-
- if (new_w->vdrawing_area.visual != current->vdrawing_area.visual) {
- new_w->vdrawing_area.visual = current->vdrawing_area.visual;
-#ifdef DEBUG
- fprintf(stdout, "VDrawingArea.SetValues: can't change visual from: visualID=%ld to visualID=%ld\n",
- current->vdrawing_area.visual->visualid,
- new_w->vdrawing_area.visual->visualid);
-#endif
-
- }
-
- return (False);
-}
-
-int
-FindWindowInList (Window parentWindow, Window *colormap_windows, int count)
-{
- int i;
-
- for (i = 0; i < count; i++)
- if (colormap_windows [i] == parentWindow)
- return i;
- return -1;
-}
-
-static void
-Realize(w, value_mask, attributes)
- Widget w;
- XtValueMask *value_mask;
- XSetWindowAttributes *attributes;
-{
- Widget parent;
- Status status;
- Window *colormap_windows;
- Window *new_colormap_windows;
- int count;
- int i;
- VDrawingAreaWidget vd = (VDrawingAreaWidget)w;
-
-#ifdef DEBUG
- fprintf(stdout, "VDrawingArea.Realize: visualID=%ld, depth=%d\n",
- vd->vdrawing_area.visual->visualid, w->core.depth);
-#endif
-
- /* 4328588:
- * Since we have our own Realize() function, we don't execute the one for
- * our super-super class, XmManager, and miss the code which checks that
- * height and width != 0. I've added that here. -bchristi
- */
- if (!XtWidth(w)) XtWidth(w) = 1 ;
- if (!XtHeight(w)) XtHeight(w) = 1 ;
-
- w->core.window = XCreateWindow (XtDisplay (w), XtWindow (w->core.parent),
- w->core.x, w->core.y, w->core.width, w->core.height,
- 0, w->core.depth, InputOutput,
- vd->vdrawing_area.visual,
- *value_mask, attributes );
-
- /* Need to add this window to the list of Colormap windows */
- parent = XtParent (w);
- while ((parent != NULL) && (!(XtIsShell (parent))))
- parent = XtParent (parent);
- if (parent == NULL) {
- fprintf (stderr, "NO TopLevel widget?!\n");
- return;
- }
-
- status = XGetWMColormapWindows (XtDisplay (w), XtWindow (parent),
- &colormap_windows, &count);
-
- /* If status is zero, add this window and shell to the list
- of colormap Windows */
- if (status == 0) {
- new_colormap_windows = (Window *) calloc (2, sizeof (Window));
- new_colormap_windows [0] = XtWindow (w);
- new_colormap_windows [1] = XtWindow (parent);
- XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
- new_colormap_windows, 2);
- free (new_colormap_windows);
- } else {
- /* Check if parent is already in the list */
- int parent_entry = -1;
-
- if (count > 0)
- parent_entry = FindWindowInList (XtWindow (parent),
- colormap_windows, count);
- if (parent_entry == -1) { /* Parent not in list */
- new_colormap_windows = (Window *) calloc (count + 2,
- sizeof (Window));
- new_colormap_windows [0] = XtWindow (w);
- new_colormap_windows [1] = XtWindow (parent);
- for (i = 0; i < count; i++)
- new_colormap_windows [i + 2] = colormap_windows [i];
- XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
- new_colormap_windows, count + 2);
-
- } else { /* parent already in list, just add new window */
- new_colormap_windows = (Window *) calloc (count + 1,
- sizeof (Window));
- new_colormap_windows [0] = XtWindow (w);
- for (i = 0; i < count; i++)
- new_colormap_windows [i + 1] = colormap_windows [i];
- XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
- new_colormap_windows, count + 1);
- }
- free (new_colormap_windows);
- XFree (colormap_windows);
- }
-
-
-}
-
-static void
-Destroy(Widget widget)
-{
- Status status;
- Widget parent;
- Window *colormap_windows;
- Window *new_colormap_windows;
- int count;
- int listEntry;
- int i;
- int j;
-
- /* Need to get this window's parent shell first */
- parent = XtParent (widget);
- while ((parent != NULL) && (!(XtIsShell (parent))))
- parent = XtParent (parent);
- if (parent == NULL) {
- fprintf (stderr, "NO TopLevel widget?!\n");
- return;
- }
-
- status = XGetWMColormapWindows (XtDisplay (widget), XtWindow (parent),
- &colormap_windows, &count);
-
- /* If status is zero, then there were no colormap windows for
- the parent ?? */
-
- if (status == 0)
- return;
-
- /* Remove this window from the list of colormap windows */
- listEntry = FindWindowInList (XtWindow (widget), colormap_windows,
- count);
-
- new_colormap_windows = (Window *) calloc (count - 1, sizeof (Window));
- j = 0;
- for (i = 0; i < count; i++) {
- if (i == listEntry)
- continue;
- new_colormap_windows [j] = colormap_windows [i];
- j++;
- }
- XSetWMColormapWindows (XtDisplay (widget), XtWindow (parent),
- new_colormap_windows, count - 1);
- free (new_colormap_windows);
- XFree (colormap_windows);
-
-}
-#endif /* !HEADLESS */
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 1997, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. 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.
- */
-
-#ifndef _VDrawingArea_h_
-#define _VDrawingArea_h_
-
-#ifndef HEADLESS
-extern WidgetClass vDrawingAreaClass;
-
-typedef struct _VDrawingAreaClassRec *VDrawingAreaWidgetClass;
-typedef struct _VDrawingAreaRec *VDrawingAreaWidget;
-#endif /* !HEADLESS */
-
-#endif /* !_VDrawingArea_h_ */
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1997, 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.
- */
-
-#ifndef _VDrawingAreaP_h_
-#define _VDrawingAreaP_h_
-
-#include <Xm/DrawingAP.h>
-#include "VDrawingArea.h"
-
-
-/***************************************************************
- * VDrawingArea Widget Data Structures
- *
- *
- **************************************************************/
-
-/* Define part class structure */
-typedef struct _VDrawingAreaClass {
- XtPointer extension;
-} VDrawingAreaClassPart;
-
-/* Define the full class record */
-typedef struct _VDrawingAreaClassRec {
- CoreClassPart core_class;
- CompositeClassPart composite_class;
- ConstraintClassPart constraint_class;
- XmManagerClassPart manager_class;
- XmDrawingAreaClassPart drawing_area_class;
- VDrawingAreaClassPart vdrawingarea_class;
-} VDrawingAreaClassRec;
-
-/* External definition for class record */
-extern VDrawingAreaClassRec vDrawingAreaClassRec;
-
-typedef struct {
- Visual *visual;
-} VDrawingAreaPart;
-
-/****************************************************************
- *
- * Full instance record declaration
- *
- ****************************************************************/
-
-typedef struct _VDrawingAreaRec
-{
- CorePart core;
- CompositePart composite;
- ConstraintPart constraint;
- XmManagerPart manager;
- XmDrawingAreaPart drawing_area;
- VDrawingAreaPart vdrawing_area;
-} VDrawingAreaRec;
-
-
-
-#endif /* !_VDrawingAreaP_h_ */
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c Fri May 06 06:23:30 2016 -0700
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
+#include <X11/keysym.h>
#include <sys/time.h>
#include "awt.h"
@@ -40,7 +41,6 @@
#define THROW_OUT_OF_MEMORY_ERROR() \
JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
-#define SETARG(name, value) XtSetArg(args[argc], name, value); argc++
struct X11InputMethodIDs {
jfieldID pData;
@@ -590,7 +590,7 @@
char **mclr;
int mccr = 0;
char *dsr;
- Pixel bg, fg, light, dim;
+ unsigned long bg, fg, light, dim;
int x, y, off_x, off_y, xx, yy;
unsigned int w, h, bw, depth;
XGCValues values;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
#include "awt_GraphicsEnv.h"
#define XK_MISCELLANY
#include <X11/keysymdef.h>
-#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/Xmd.h>
#include <X11/extensions/xtestext1.h>
@@ -45,7 +44,7 @@
#include "wsutils.h"
#include "list.h"
#include "multiVis.h"
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
#if defined(__linux__) || defined(MACOSX)
#include <sys/socket.h>
@@ -264,70 +263,10 @@
int index;
if (isGtkSupported) {
- GdkPixbuf *pixbuf;
- (*fp_gdk_threads_enter)();
- GdkWindow *root = (*fp_gdk_get_default_root_window)();
-
- pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL,
- x, y, 0, 0, width, height);
- if (pixbuf && scale != 1) {
- GdkPixbuf *scaledPixbuf;
- x /= scale;
- y /= scale;
- width /= scale;
- height /= scale;
- dx /= scale;
- dy /= scale;
- scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
- GDK_INTERP_BILINEAR);
- (*fp_g_object_unref)(pixbuf);
- pixbuf = scaledPixbuf;
- }
-
- if (pixbuf) {
- int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
- int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
-
- if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
- && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
- && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
- && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
- && nchan >= 3
- ) {
- guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
-
- ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
- if (!ary) {
- (*fp_g_object_unref)(pixbuf);
- (*fp_gdk_threads_leave)();
- AWT_UNLOCK();
- return;
- }
-
- for (_y = 0; _y < height; _y++) {
- for (_x = 0; _x < width; _x++) {
- p = pix + _y * stride + _x * nchan;
-
- index = (_y + dy) * jwidth + (_x + dx);
- ary[index] = 0xff000000
- | (p[0] << 16)
- | (p[1] << 8)
- | (p[2]);
-
- }
- }
- (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
- if ((*env)->ExceptionCheck(env)) {
- (*fp_g_object_unref)(pixbuf);
- (*fp_gdk_threads_leave)();
- AWT_UNLOCK();
- return;
- }
- gtk_failed = FALSE;
- }
- (*fp_g_object_unref)(pixbuf);
- }
- (*fp_gdk_threads_leave)();
+ gtk->gdk_threads_enter();
+ gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
+ height, jwidth, dx, dy, scale);
+ gtk->gdk_threads_leave();
}
if (gtk_failed) {
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
#ifndef HEADLESS
#include "awt.h"
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
#endif /* !HEADLESS */
@@ -45,13 +45,12 @@
/*
* Class: sun_awt_UNIXToolkit
* Method: check_gtk
- * Signature: ()Z
+ * Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
-Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass)
-{
+Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) {
#ifndef HEADLESS
- return (jboolean)gtk2_check_version();
+ return (jboolean)gtk_check_version(version);
#else
return JNI_FALSE;
#endif /* !HEADLESS */
@@ -61,13 +60,13 @@
/*
* Class: sun_awt_UNIXToolkit
* Method: load_gtk
- * Signature: ()Z
+ * Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
-Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass)
-{
+Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version,
+ jboolean verbose) {
#ifndef HEADLESS
- return (jboolean)gtk2_load(env);
+ return (jboolean)gtk_load(env, version, verbose);
#else
return JNI_FALSE;
#endif /* !HEADLESS */
@@ -83,16 +82,14 @@
Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass)
{
#ifndef HEADLESS
- return (jboolean)gtk2_unload();
+ return (jboolean)gtk->unload();
#else
return JNI_FALSE;
#endif /* !HEADLESS */
}
-jboolean _icon_upcall(JNIEnv *env, jobject this, GdkPixbuf *pixbuf)
+jboolean init_method(JNIEnv *env, jobject this)
{
- jboolean result = JNI_FALSE;
-
if (this_class == NULL) {
this_class = (*env)->NewGlobalRef(env,
(*env)->GetObjectClass(env, this));
@@ -100,33 +97,7 @@
"loadIconCallback", "([BIIIIIZ)V");
CHECK_NULL_RETURN(icon_upcall_method, JNI_FALSE);
}
-
- if (pixbuf != NULL)
- {
- guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
- int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
- int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
- int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
- int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
- int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
- gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
-
- /* Copy the data array into a Java structure so we can pass it back. */
- jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
-
- (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
- (jbyte *)pixbuf_data);
-
- /* Release the pixbuf. */
- (*fp_g_object_unref)(pixbuf);
-
- /* Call the callback method to create the image on the Java side. */
- (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
- width, height, row_stride, bps, channels, alpha);
- result = JNI_TRUE;
- }
- return result;
+ return JNI_TRUE;
}
/*
@@ -144,7 +115,6 @@
int len;
char *filename_str = NULL;
GError **error = NULL;
- GdkPixbuf *pixbuf;
if (filename == NULL)
{
@@ -158,13 +128,17 @@
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
return JNI_FALSE;
}
+ if (!init_method(env, this) ) {
+ return JNI_FALSE;
+ }
(*env)->GetStringUTFRegion(env, filename, 0, len, filename_str);
- pixbuf = (*fp_gdk_pixbuf_new_from_file)(filename_str, error);
+ jboolean result = gtk->get_file_icon_data(env, filename_str, error,
+ icon_upcall_method, this);
/* Release the strings we've allocated. */
free(filename_str);
- return _icon_upcall(env, this, pixbuf);
+ return result;
#else /* HEADLESS */
return JNI_FALSE;
#endif /* !HEADLESS */
@@ -186,7 +160,6 @@
int len;
char *stock_id_str = NULL;
char *detail_str = NULL;
- GdkPixbuf *pixbuf;
if (stock_id == NULL)
{
@@ -215,8 +188,12 @@
(*env)->GetStringUTFRegion(env, detail, 0, len, detail_str);
}
- pixbuf = gtk2_get_stock_icon(widget_type, stock_id_str, icon_size,
- text_direction, detail_str);
+ if (!init_method(env, this) ) {
+ return JNI_FALSE;
+ }
+ jboolean result = gtk->get_icon_data(env, widget_type, stock_id_str,
+ icon_size, text_direction, detail_str,
+ icon_upcall_method, this);
/* Release the strings we've allocated. */
free(stock_id_str);
@@ -224,8 +201,7 @@
{
free(detail_str);
}
-
- return _icon_upcall(env, this, pixbuf);
+ return result;
#else /* HEADLESS */
return JNI_FALSE;
#endif /* !HEADLESS */
@@ -279,11 +255,25 @@
{
char *ret;
- ret = fp_gtk_check_version(major, minor, micro);
+ ret = gtk->gtk_check_version(major, minor, micro);
if (ret == NULL) {
return TRUE;
}
- free(ret);
return FALSE;
}
+
+/*
+ * Class: sun_awt_UNIXToolkit
+ * Method: get_gtk_version
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass)
+{
+#ifndef HEADLESS
+ return gtk ? gtk->version : GTK_ANY;
+#else
+ return GTK_ANY;
+#endif /* !HEADLESS */
+}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c Fri May 06 06:23:30 2016 -0700
@@ -29,7 +29,6 @@
#include "awt_p.h"
#include "color.h"
-#include <X11/IntrinsicP.h>
#include <X11/Xatom.h>
#include <X11/Xmd.h>
#include <X11/Xutil.h>
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Fri May 06 06:23:30 2016 -0700
@@ -35,52 +35,18 @@
#include <jni_util.h>
#include "awt.h"
-#define GTK2_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0")
-#define GTK2_LIB JNI_LIB_NAME("gtk-x11-2.0")
#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
-#define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0)
-#define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1)
-#define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2)
-#define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3)
-#define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4)
-#define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5)
-#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6)
-#define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7)
-#define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8)
-#define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9)
-#define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10)
-#define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11)
-#define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12)
-#define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13)
-#define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14)
-#define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15)
-#define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16)
-#define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17)
-#define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18)
-#define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19)
-#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
-
#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())
#define G_TYPE_FUNDAMENTAL_SHIFT (2)
#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define CONV_BUFFER_SIZE 128
#define NO_SYMBOL_EXCEPTION 1
-/* SynthConstants */
-const gint ENABLED = 1 << 0;
-const gint MOUSE_OVER = 1 << 1;
-const gint PRESSED = 1 << 2;
-const gint DISABLED = 1 << 3;
-const gint FOCUSED = 1 << 8;
-const gint SELECTED = 1 << 9;
-const gint DEFAULT = 1 << 10;
-
static void *gtk2_libhandle = NULL;
static void *gthread_libhandle = NULL;
@@ -105,54 +71,6 @@
static gboolean new_combo = TRUE;
const char ENV_PREFIX[] = "GTK_MODULES=";
-/*******************/
-enum GtkWidgetType
-{
- _GTK_ARROW_TYPE,
- _GTK_BUTTON_TYPE,
- _GTK_CHECK_BUTTON_TYPE,
- _GTK_CHECK_MENU_ITEM_TYPE,
- _GTK_COLOR_SELECTION_DIALOG_TYPE,
- _GTK_COMBO_BOX_TYPE,
- _GTK_COMBO_BOX_ARROW_BUTTON_TYPE,
- _GTK_COMBO_BOX_TEXT_FIELD_TYPE,
- _GTK_CONTAINER_TYPE,
- _GTK_ENTRY_TYPE,
- _GTK_FRAME_TYPE,
- _GTK_HANDLE_BOX_TYPE,
- _GTK_HPANED_TYPE,
- _GTK_HPROGRESS_BAR_TYPE,
- _GTK_HSCALE_TYPE,
- _GTK_HSCROLLBAR_TYPE,
- _GTK_HSEPARATOR_TYPE,
- _GTK_IMAGE_TYPE,
- _GTK_MENU_TYPE,
- _GTK_MENU_BAR_TYPE,
- _GTK_MENU_ITEM_TYPE,
- _GTK_NOTEBOOK_TYPE,
- _GTK_LABEL_TYPE,
- _GTK_RADIO_BUTTON_TYPE,
- _GTK_RADIO_MENU_ITEM_TYPE,
- _GTK_SCROLLED_WINDOW_TYPE,
- _GTK_SEPARATOR_MENU_ITEM_TYPE,
- _GTK_SEPARATOR_TOOL_ITEM_TYPE,
- _GTK_SPIN_BUTTON_TYPE,
- _GTK_TEXT_VIEW_TYPE,
- _GTK_TOGGLE_BUTTON_TYPE,
- _GTK_TOOLBAR_TYPE,
- _GTK_TOOLTIP_TYPE,
- _GTK_TREE_VIEW_TYPE,
- _GTK_VIEWPORT_TYPE,
- _GTK_VPANED_TYPE,
- _GTK_VPROGRESS_BAR_TYPE,
- _GTK_VSCALE_TYPE,
- _GTK_VSCROLLBAR_TYPE,
- _GTK_VSEPARATOR_TYPE,
- _GTK_WINDOW_TYPE,
- _GTK_DIALOG_TYPE,
- _GTK_WIDGET_TYPE_SIZE
-};
-
static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];
@@ -359,20 +277,6 @@
static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);
/* Method bodies */
-const char *getStrFor(JNIEnv *env, jstring val)
-{
- int length = (*env)->GetStringLength(env, val);
- if (length > CONV_BUFFER_SIZE-1)
- {
- length = CONV_BUFFER_SIZE-1;
-#ifdef DEBUG
- fprintf(stderr, "Note: Detail is too long: %d chars\n", length);
-#endif /* DEBUG */
- }
-
- (*env)->GetStringUTFRegion(env, val, 0, length, convertionBuffer);
- return convertionBuffer;
-}
static void throw_exception(JNIEnv *env, const char* name, const char* message)
{
@@ -408,33 +312,34 @@
return result;
}
-gboolean gtk2_check_version()
+gboolean gtk2_check(const char* lib_name, int flags)
{
if (gtk2_libhandle != NULL) {
/* We've already successfully opened the GTK libs, so return true. */
return TRUE;
} else {
void *lib = NULL;
- gboolean result = FALSE;
- lib = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
+ lib = dlopen(lib_name, flags);
+
if (lib == NULL) {
- lib = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
- if (lib == NULL) {
- return FALSE;
- }
+ return FALSE;
+ }
+
+ if (flags & RTLD_NOLOAD) {
+ return TRUE;
}
fp_gtk_check_version = dlsym(lib, "gtk_check_version");
/* Check for GTK 2.2+ */
if (!fp_gtk_check_version(2, 2, 0)) {
- result = TRUE;
+ return TRUE;
}
// 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065
// dlclose(lib);
- return result;
+ return FALSE;
}
}
@@ -450,7 +355,7 @@
} while(0);
-void update_supported_actions(JNIEnv *env) {
+static void update_supported_actions(JNIEnv *env) {
GVfs * (*fp_g_vfs_get_default) (void);
const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);
const gchar * const * schemes = NULL;
@@ -513,7 +418,7 @@
/**
* Functions for awt_Desktop.c
*/
-gboolean gtk2_show_uri_load(JNIEnv *env) {
+static gboolean gtk2_show_uri_load(JNIEnv *env) {
gboolean success = FALSE;
dlerror();
const char *gtk_version = fp_gtk_check_version(2, 14, 0);
@@ -537,6 +442,7 @@
fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");
#endif /* DEBUG */
} else {
+ gtk->gtk_show_uri = fp_gtk_show_uri;
update_supported_actions(env);
success = TRUE;
}
@@ -547,7 +453,7 @@
/**
* Functions for sun_awt_X11_GtkFileDialogPeer.c
*/
-void gtk2_file_chooser_load()
+static void gtk2_file_chooser_load()
{
fp_gtk_file_chooser_get_filename = dl_symbol(
"gtk_file_chooser_get_filename");
@@ -576,7 +482,7 @@
fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid");
}
-gboolean gtk2_load(JNIEnv *env)
+GtkApi* gtk2_load(JNIEnv *env, const char* lib_name)
{
gboolean result;
int i;
@@ -584,11 +490,9 @@
int (*io_handler)();
char *gtk_modules_env;
- gtk2_libhandle = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
+ gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);
if (gtk2_libhandle == NULL) {
- gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
- if (gtk2_libhandle == NULL)
- return FALSE;
+ return FALSE;
}
gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
@@ -962,8 +866,12 @@
{
gtk2_widgets[i] = NULL;
}
-
- return result;
+ if (result) {
+ GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));
+ gtk2_init(gtk);
+ return gtk;
+ }
+ return NULL;
}
int gtk2_unload()
@@ -1007,7 +915,7 @@
/* Dispatch all pending events from the GTK event loop.
* This is needed to catch theme change and update widgets' style.
*/
-void flush_gtk_event_loop()
+static void flush_gtk_event_loop()
{
while( (*fp_g_main_context_iteration)(NULL, FALSE));
}
@@ -1056,7 +964,7 @@
* comparing results. This can be optimized by using subclassed pixmap and
* doing the second drawing only if necessary.
*/
-void gtk2_init_painting(JNIEnv *env, gint width, gint height)
+static void gtk2_init_painting(JNIEnv *env, gint width, gint height)
{
GdkGC *gc;
GdkPixbuf *white, *black;
@@ -1116,7 +1024,7 @@
* one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
* java_awt_Transparency_TRANSLUCENT.
*/
-gint gtk2_copy_image(gint *dst, gint width, gint height)
+static gint gtk2_copy_image(gint *dst, gint width, gint height)
{
gint i, j, r, g, b;
guchar *white, *black;
@@ -1778,7 +1686,7 @@
x, y, w, h);
}
-void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
gint x, gint y, gint width, gint height,
gint synth_state, GtkTextDirection dir)
@@ -1948,7 +1856,7 @@
x, y, width, height, gap_side, gap_x, gap_width);
}
-void gtk2_paint_check(WidgetType widget_type, gint synth_state,
+static void gtk2_paint_check(WidgetType widget_type, gint synth_state,
const gchar *detail, gint x, gint y, gint width, gint height)
{
GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
@@ -1965,7 +1873,7 @@
x, y, width, height);
}
-void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
gint x, gint y, gint width, gint height)
{
@@ -1978,7 +1886,7 @@
x, y, width, height);
}
-void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
const gchar *detail, gint x, gint y, gint width, gint height,
GtkExpanderStyle expander_style)
{
@@ -1991,7 +1899,7 @@
x + width / 2, y + height / 2, expander_style);
}
-void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
gint x, gint y, gint width, gint height, GtkPositionType gap_side)
{
@@ -2004,7 +1912,7 @@
x, y, width, height, gap_side);
}
-void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
gint x, gint y, gint width, gint height, gboolean has_focus)
{
@@ -2023,7 +1931,7 @@
x, y, width, height);
}
-void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
const char *detail, gint x, gint y, gint width, gint height)
{
gtk2_widget = gtk2_get_widget(widget_type);
@@ -2033,7 +1941,7 @@
NULL, gtk2_widget, detail, x, y, width, height);
}
-void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
gint x, gint y, gint width, gint height, GtkOrientation orientation)
{
@@ -2046,7 +1954,7 @@
x, y, width, height, orientation);
}
-void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
const gchar *detail, gint x, gint y, gint width, gint height)
{
gtk2_widget = gtk2_get_widget(widget_type);
@@ -2056,7 +1964,7 @@
NULL, gtk2_widget, detail, x, x + width, y);
}
-void gtk2_paint_option(WidgetType widget_type, gint synth_state,
+static void gtk2_paint_option(WidgetType widget_type, gint synth_state,
const gchar *detail, gint x, gint y, gint width, gint height)
{
GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
@@ -2073,7 +1981,7 @@
x, y, width, height);
}
-void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
gint x, gint y, gint width, gint height,
gint synth_state, GtkTextDirection dir)
@@ -2123,9 +2031,10 @@
gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);
}
-void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height, GtkOrientation orientation)
+ gint x, gint y, gint width, gint height, GtkOrientation orientation,
+ gboolean has_focus)
{
gtk2_widget = gtk2_get_widget(widget_type);
(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,
@@ -2136,7 +2045,7 @@
x, y, width, height, orientation);
}
-void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
const gchar *detail, gint x, gint y, gint width, gint height)
{
gtk2_widget = gtk2_get_widget(widget_type);
@@ -2146,7 +2055,7 @@
NULL, gtk2_widget, detail, y, y + height, x);
}
-void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
+static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
gint x, gint y, gint width, gint height)
{
gtk2_widget = gtk2_get_widget(widget_type);
@@ -2156,7 +2065,7 @@
gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);
}
-GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
+static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
GtkIconSize size, GtkTextDirection direction, const char *detail)
{
init_containers();
@@ -2166,8 +2075,52 @@
return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);
}
+static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,
+ jmethodID icon_upcall_method, jobject this) {
+ if (!pixbuf) {
+ return JNI_FALSE;
+ }
+ guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+ if (pixbuf_data) {
+ int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+ int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
+ int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
+ int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
+ int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+ gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
+
+ jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
+ JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+ (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
+ (jbyte *)pixbuf_data);
+ (*fp_g_object_unref)(pixbuf);
+
+ /* Call the callback method to create the image on the Java side. */
+ (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
+ width, height, row_stride, bps, channels, alpha);
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename,
+ GError **error, jmethodID icon_upcall_method, jobject this) {
+ GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);
+ return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
+static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type,
+ const gchar *stock_id, GtkIconSize size,
+ GtkTextDirection direction, const char *detail,
+ jmethodID icon_upcall_method, jobject this) {
+ GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size,
+ direction, detail);
+ return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
/*************************************************/
-gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)
+static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)
{
init_containers();
@@ -2176,7 +2129,7 @@
return style->xthickness;
}
-gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)
+static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)
{
init_containers();
@@ -2186,12 +2139,12 @@
}
/*************************************************/
-guint8 recode_color(guint16 channel)
+static guint8 recode_color(guint16 channel)
{
return (guint8)(channel>>8);
}
-gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
+static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
GtkStateType state_type, ColorType color_type)
{
gint result = 0;
@@ -2243,19 +2196,19 @@
}
/*************************************************/
-jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
-jobject create_Integer(JNIEnv *env, jint int_value);
-jobject create_Long(JNIEnv *env, jlong long_value);
-jobject create_Float(JNIEnv *env, jfloat float_value);
-jobject create_Double(JNIEnv *env, jdouble double_value);
-jobject create_Character(JNIEnv *env, jchar char_value);
-jobject create_Insets(JNIEnv *env, GtkBorder *border);
+static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
+static jobject create_Integer(JNIEnv *env, jint int_value);
+static jobject create_Long(JNIEnv *env, jlong long_value);
+static jobject create_Float(JNIEnv *env, jfloat float_value);
+static jobject create_Double(JNIEnv *env, jdouble double_value);
+static jobject create_Character(JNIEnv *env, jchar char_value);
+static jobject create_Insets(JNIEnv *env, GtkBorder *border);
-jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring jkey)
+static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type,
+ const char* key)
{
init_containers();
- const char* key = getStrFor(env, jkey);
gtk2_widget = gtk2_get_widget(widget_type);
GValue value;
@@ -2376,7 +2329,7 @@
return NULL;
}
-void gtk2_set_range_value(WidgetType widget_type, jdouble value,
+static void gtk2_set_range_value(WidgetType widget_type, jdouble value,
jdouble min, jdouble max, jdouble visible)
{
GtkAdjustment *adj;
@@ -2391,7 +2344,7 @@
}
/*************************************************/
-jobject create_Object(JNIEnv *env, jmethodID *cid,
+static jobject create_Object(JNIEnv *env, jmethodID *cid,
const char* class_name,
const char* signature,
jvalue* value)
@@ -2494,7 +2447,7 @@
}
/*********************************************/
-jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
+static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
{
init_containers();
@@ -2513,7 +2466,7 @@
}
/***********************************************/
-jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
+static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
{
jobject result = NULL;
gchar* strval = NULL;
@@ -2525,21 +2478,21 @@
return result;
}
-jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
+static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
{
gint intval = NULL;
(*fp_g_object_get)(settings, key, &intval, NULL);
return create_Integer(env, intval);
}
-jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
+static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
{
gint intval = NULL;
(*fp_g_object_get)(settings, key, &intval, NULL);
return create_Boolean(env, intval);
}
-jobject gtk2_get_setting(JNIEnv *env, Setting property)
+static jobject gtk2_get_setting(JNIEnv *env, Setting property)
{
GtkSettings* settings = (*fp_gtk_settings_get_default)();
@@ -2557,3 +2510,148 @@
return NULL;
}
+
+static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x,
+ jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) {
+ GdkPixbuf *pixbuf;
+ jint *ary;
+
+ GdkWindow *root = (*fp_gdk_get_default_root_window)();
+
+ pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y,
+ 0, 0, width, height);
+ if (pixbuf && scale != 1) {
+ GdkPixbuf *scaledPixbuf;
+ x /= scale;
+ y /= scale;
+ width /= scale;
+ height /= scale;
+ dx /= scale;
+ dy /= scale;
+ scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
+ GDK_INTERP_BILINEAR);
+ (*fp_g_object_unref)(pixbuf);
+ pixbuf = scaledPixbuf;
+ }
+
+ if (pixbuf) {
+ int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+ int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+
+ if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
+ && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
+ && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
+ && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
+ && nchan >= 3
+ ) {
+ guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+
+ ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
+ if (ary) {
+ jint _x, _y;
+ int index;
+ for (_y = 0; _y < height; _y++) {
+ for (_x = 0; _x < width; _x++) {
+ p = pix + _y * stride + _x * nchan;
+
+ index = (_y + dy) * jwidth + (_x + dx);
+ ary[index] = 0xff000000
+ | (p[0] << 16)
+ | (p[1] << 8)
+ | (p[2]);
+
+ }
+ }
+ (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
+ }
+ }
+ (*fp_g_object_unref)(pixbuf);
+ }
+ return JNI_FALSE;
+}
+
+static GdkWindow* gtk2_get_window(void *widget) {
+ return ((GtkWidget*)widget)->window;
+}
+
+void gtk2_init(GtkApi* gtk) {
+ gtk->version = GTK_2;
+
+ gtk->show_uri_load = >k2_show_uri_load;
+ gtk->unload = >k2_unload;
+ gtk->flush_event_loop = &flush_gtk_event_loop;
+ gtk->gtk_check_version = fp_gtk_check_version;
+ gtk->get_setting = >k2_get_setting;
+
+ gtk->paint_arrow = >k2_paint_arrow;
+ gtk->paint_box = >k2_paint_box;
+ gtk->paint_box_gap = >k2_paint_box_gap;
+ gtk->paint_expander = >k2_paint_expander;
+ gtk->paint_extension = >k2_paint_extension;
+ gtk->paint_flat_box = >k2_paint_flat_box;
+ gtk->paint_focus = >k2_paint_focus;
+ gtk->paint_handle = >k2_paint_handle;
+ gtk->paint_hline = >k2_paint_hline;
+ gtk->paint_vline = >k2_paint_vline;
+ gtk->paint_option = >k2_paint_option;
+ gtk->paint_shadow = >k2_paint_shadow;
+ gtk->paint_slider = >k2_paint_slider;
+ gtk->paint_background = >k_paint_background;
+ gtk->paint_check = >k2_paint_check;
+ gtk->set_range_value = >k2_set_range_value;
+
+ gtk->init_painting = >k2_init_painting;
+ gtk->copy_image = >k2_copy_image;
+
+ gtk->get_xthickness = >k2_get_xthickness;
+ gtk->get_ythickness = >k2_get_ythickness;
+ gtk->get_color_for_state = >k2_get_color_for_state;
+ gtk->get_class_value = >k2_get_class_value;
+
+ gtk->get_pango_font_name = >k2_get_pango_font_name;
+ gtk->get_icon_data = >k2_get_icon_data;
+ gtk->get_file_icon_data = >k2_get_file_icon_data;
+ gtk->gdk_threads_enter = fp_gdk_threads_enter;
+ gtk->gdk_threads_leave = fp_gdk_threads_leave;
+ gtk->gtk_show_uri = fp_gtk_show_uri;
+ gtk->get_drawable_data = >k2_get_drawable_data;
+ gtk->g_free = fp_g_free;
+
+ gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;
+ gtk->gtk_widget_hide = fp_gtk_widget_hide;
+ gtk->gtk_main_quit = fp_gtk_main_quit;
+ gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;
+ gtk->gtk_file_chooser_set_current_folder =
+ fp_gtk_file_chooser_set_current_folder;
+ gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;
+ gtk->gtk_file_chooser_set_current_name =
+ fp_gtk_file_chooser_set_current_name;
+ gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;
+ gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;
+ gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;
+ gtk->gtk_file_filter_new = fp_gtk_file_filter_new;
+ gtk->gtk_file_chooser_set_do_overwrite_confirmation =
+ fp_gtk_file_chooser_set_do_overwrite_confirmation;
+ gtk->gtk_file_chooser_set_select_multiple =
+ fp_gtk_file_chooser_set_select_multiple;
+ gtk->gtk_file_chooser_get_current_folder =
+ fp_gtk_file_chooser_get_current_folder;
+ gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;
+ gtk->gtk_g_slist_length = fp_gtk_g_slist_length;
+ gtk->g_signal_connect_data = fp_g_signal_connect_data;
+ gtk->gtk_widget_show = fp_gtk_widget_show;
+ gtk->gtk_main = fp_gtk_main;
+ gtk->gtk_main_level = fp_gtk_main_level;
+ gtk->g_path_get_dirname = fp_g_path_get_dirname;
+ gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;
+ gtk->gtk_widget_destroy = fp_gtk_widget_destroy;
+ gtk->gtk_window_present = fp_gtk_window_present;
+ gtk->gtk_window_move = fp_gtk_window_move;
+ gtk->gtk_window_resize = fp_gtk_window_resize;
+ gtk->get_window = >k2_get_window;
+
+ gtk->g_object_unref = fp_g_object_unref;
+ gtk->g_list_append = fp_g_list_append;
+ gtk->g_list_free = fp_g_list_free;
+ gtk->g_list_free_full = fp_g_list_free_full;
+}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Fri May 06 06:23:30 2016 -0700
@@ -28,232 +28,11 @@
#include <stdlib.h>
#include <jni.h>
#include <X11/X.h>
-
-#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
-#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type))
-#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ())
-#define GTK_FILE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser))
-#define fp_g_signal_connect(instance, detailed_signal, c_handler, data) \
- fp_g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)
-#define G_CALLBACK(f) ((GCallback) (f))
-#define G_TYPE_FUNDAMENTAL_SHIFT (2)
-#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
-#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
-#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
-#define GTK_STOCK_CANCEL "gtk-cancel"
-#define GTK_STOCK_SAVE "gtk-save"
-#define GTK_STOCK_OPEN "gtk-open"
-#define GDK_CURRENT_TIME 0L
-
-typedef enum _WidgetType
-{
- BUTTON, /* GtkButton */
- CHECK_BOX, /* GtkCheckButton */
- CHECK_BOX_MENU_ITEM, /* GtkCheckMenuItem */
- COLOR_CHOOSER, /* GtkColorSelectionDialog */
- COMBO_BOX, /* GtkComboBox */
- COMBO_BOX_ARROW_BUTTON, /* GtkComboBoxEntry */
- COMBO_BOX_TEXT_FIELD, /* GtkComboBoxEntry */
- DESKTOP_ICON, /* GtkLabel */
- DESKTOP_PANE, /* GtkContainer */
- EDITOR_PANE, /* GtkTextView */
- FORMATTED_TEXT_FIELD, /* GtkEntry */
- HANDLE_BOX, /* GtkHandleBox */
- HPROGRESS_BAR, /* GtkProgressBar */
- HSCROLL_BAR, /* GtkHScrollbar */
- HSCROLL_BAR_BUTTON_LEFT, /* GtkHScrollbar */
- HSCROLL_BAR_BUTTON_RIGHT, /* GtkHScrollbar */
- HSCROLL_BAR_TRACK, /* GtkHScrollbar */
- HSCROLL_BAR_THUMB, /* GtkHScrollbar */
- HSEPARATOR, /* GtkHSeparator */
- HSLIDER, /* GtkHScale */
- HSLIDER_TRACK, /* GtkHScale */
- HSLIDER_THUMB, /* GtkHScale */
- HSPLIT_PANE_DIVIDER, /* GtkHPaned */
- INTERNAL_FRAME, /* GtkWindow */
- INTERNAL_FRAME_TITLE_PANE, /* GtkLabel */
- IMAGE, /* GtkImage */
- LABEL, /* GtkLabel */
- LIST, /* GtkTreeView */
- MENU, /* GtkMenu */
- MENU_BAR, /* GtkMenuBar */
- MENU_ITEM, /* GtkMenuItem */
- MENU_ITEM_ACCELERATOR, /* GtkLabel */
- OPTION_PANE, /* GtkMessageDialog */
- PANEL, /* GtkContainer */
- PASSWORD_FIELD, /* GtkEntry */
- POPUP_MENU, /* GtkMenu */
- POPUP_MENU_SEPARATOR, /* GtkSeparatorMenuItem */
- RADIO_BUTTON, /* GtkRadioButton */
- RADIO_BUTTON_MENU_ITEM, /* GtkRadioMenuItem */
- ROOT_PANE, /* GtkContainer */
- SCROLL_PANE, /* GtkScrolledWindow */
- SPINNER, /* GtkSpinButton */
- SPINNER_ARROW_BUTTON, /* GtkSpinButton */
- SPINNER_TEXT_FIELD, /* GtkSpinButton */
- SPLIT_PANE, /* GtkPaned */
- TABBED_PANE, /* GtkNotebook */
- TABBED_PANE_TAB_AREA, /* GtkNotebook */
- TABBED_PANE_CONTENT, /* GtkNotebook */
- TABBED_PANE_TAB, /* GtkNotebook */
- TABLE, /* GtkTreeView */
- TABLE_HEADER, /* GtkButton */
- TEXT_AREA, /* GtkTextView */
- TEXT_FIELD, /* GtkEntry */
- TEXT_PANE, /* GtkTextView */
- TITLED_BORDER, /* GtkFrame */
- TOGGLE_BUTTON, /* GtkToggleButton */
- TOOL_BAR, /* GtkToolbar */
- TOOL_BAR_DRAG_WINDOW, /* GtkToolbar */
- TOOL_BAR_SEPARATOR, /* GtkSeparatorToolItem */
- TOOL_TIP, /* GtkWindow */
- TREE, /* GtkTreeView */
- TREE_CELL, /* GtkTreeView */
- VIEWPORT, /* GtkViewport */
- VPROGRESS_BAR, /* GtkProgressBar */
- VSCROLL_BAR, /* GtkVScrollbar */
- VSCROLL_BAR_BUTTON_UP, /* GtkVScrollbar */
- VSCROLL_BAR_BUTTON_DOWN, /* GtkVScrollbar */
- VSCROLL_BAR_TRACK, /* GtkVScrollbar */
- VSCROLL_BAR_THUMB, /* GtkVScrollbar */
- VSEPARATOR, /* GtkVSeparator */
- VSLIDER, /* GtkVScale */
- VSLIDER_TRACK, /* GtkVScale */
- VSLIDER_THUMB, /* GtkVScale */
- VSPLIT_PANE_DIVIDER, /* GtkVPaned */
- WIDGET_TYPE_SIZE
-} WidgetType;
-
-typedef enum _ColorType
-{
- FOREGROUND,
- BACKGROUND,
- TEXT_FOREGROUND,
- TEXT_BACKGROUND,
- FOCUS,
- LIGHT,
- DARK,
- MID,
- BLACK,
- WHITE
-} ColorType;
-
-typedef enum _Setting
-{
- GTK_FONT_NAME,
- GTK_ICON_SIZES,
- GTK_CURSOR_BLINK,
- GTK_CURSOR_BLINK_TIME
-} Setting;
-
-/* GTK types, here to eliminate need for GTK headers at compile time */
-
-#ifndef FALSE
-#define FALSE (0)
-#define TRUE (!FALSE)
-#endif
+#include "gtk_interface.h"
#define GTK_HAS_FOCUS (1 << 12)
#define GTK_HAS_DEFAULT (1 << 14)
-
-/* basic types */
-typedef char gchar;
-typedef short gshort;
-typedef int gint;
-typedef long glong;
-typedef float gfloat;
-typedef double gdouble;
-typedef void* gpointer;
-typedef gint gboolean;
-
-typedef signed char gint8;
-typedef signed short gint16;
-typedef signed int gint32;
-
-typedef unsigned char guchar;
-typedef unsigned char guint8;
-typedef unsigned short gushort;
-typedef unsigned short guint16;
-typedef unsigned int guint;
-typedef unsigned int guint32;
-typedef unsigned int gsize;
-typedef unsigned long gulong;
-
-typedef signed long long gint64;
-typedef unsigned long long guint64;
-
-/* enumerated constants */
-typedef enum
-{
- GTK_ARROW_UP,
- GTK_ARROW_DOWN,
- GTK_ARROW_LEFT,
- GTK_ARROW_RIGHT
-} GtkArrowType;
-
-typedef enum {
- GDK_COLORSPACE_RGB
-} GdkColorspace;
-
-typedef enum
-{
- GTK_EXPANDER_COLLAPSED,
- GTK_EXPANDER_SEMI_COLLAPSED,
- GTK_EXPANDER_SEMI_EXPANDED,
- GTK_EXPANDER_EXPANDED
-} GtkExpanderStyle;
-
-typedef enum
-{
- GTK_ICON_SIZE_INVALID,
- GTK_ICON_SIZE_MENU,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- GTK_ICON_SIZE_LARGE_TOOLBAR,
- GTK_ICON_SIZE_BUTTON,
- GTK_ICON_SIZE_DND,
- GTK_ICON_SIZE_DIALOG
-} GtkIconSize;
-
-typedef enum
-{
- GTK_ORIENTATION_HORIZONTAL,
- GTK_ORIENTATION_VERTICAL
-} GtkOrientation;
-
-typedef enum
-{
- GTK_POS_LEFT,
- GTK_POS_RIGHT,
- GTK_POS_TOP,
- GTK_POS_BOTTOM
-} GtkPositionType;
-
-typedef enum
-{
- GTK_SHADOW_NONE,
- GTK_SHADOW_IN,
- GTK_SHADOW_OUT,
- GTK_SHADOW_ETCHED_IN,
- GTK_SHADOW_ETCHED_OUT
-} GtkShadowType;
-
-typedef enum
-{
- GTK_STATE_NORMAL,
- GTK_STATE_ACTIVE,
- GTK_STATE_PRELIGHT,
- GTK_STATE_SELECTED,
- GTK_STATE_INSENSITIVE
-} GtkStateType;
-
-typedef enum
-{
- GTK_TEXT_DIR_NONE,
- GTK_TEXT_DIR_LTR,
- GTK_TEXT_DIR_RTL
-} GtkTextDirection;
-
typedef enum
{
GTK_WINDOW_TOPLEVEL,
@@ -270,41 +49,15 @@
G_PARAM_PRIVATE = 1 << 5
} GParamFlags;
-typedef enum {
- GDK_INTERP_NEAREST,
- GDK_INTERP_TILES,
- GDK_INTERP_BILINEAR,
- GDK_INTERP_HYPER
-} GdkInterpType;
-
/* We define all structure pointers to be void* */
-typedef void GError;
typedef void GMainContext;
typedef void GVfs;
-typedef struct _GSList GSList;
-struct _GSList
-{
- gpointer data;
- GSList *next;
-};
-
-typedef struct _GList GList;
-
-struct _GList
-{
- gpointer data;
- GList *next;
- GList *prev;
-};
-
typedef void GdkColormap;
typedef void GdkDrawable;
typedef void GdkGC;
-typedef void GdkScreen;
typedef void GdkPixbuf;
typedef void GdkPixmap;
-typedef void GdkWindow;
typedef void GtkFixed;
typedef void GtkMenuItem;
@@ -364,7 +117,6 @@
* structures. This is a place where getting rid of gtk
* headers may be dangerous.
******************************************************/
-typedef gulong GType;
typedef struct
{
@@ -599,70 +351,9 @@
guint ellipsize : 3;
};
-typedef enum {
- GTK_RESPONSE_NONE = -1,
- GTK_RESPONSE_REJECT = -2,
- GTK_RESPONSE_ACCEPT = -3,
- GTK_RESPONSE_DELETE_EVENT = -4,
- GTK_RESPONSE_OK = -5,
- GTK_RESPONSE_CANCEL = -6,
- GTK_RESPONSE_CLOSE = -7,
- GTK_RESPONSE_YES = -8,
- GTK_RESPONSE_NO = -9,
- GTK_RESPONSE_APPLY = -10,
- GTK_RESPONSE_HELP = -11
-} GtkResponseType;
-
-typedef struct _GtkWindow GtkWindow;
-
-typedef struct _GtkFileChooser GtkFileChooser;
-
-typedef enum {
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
- GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
-} GtkFileChooserAction;
-
-typedef struct _GtkFileFilter GtkFileFilter;
-
-typedef enum {
- GTK_FILE_FILTER_FILENAME = 1 << 0,
- GTK_FILE_FILTER_URI = 1 << 1,
- GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
- GTK_FILE_FILTER_MIME_TYPE = 1 << 3
-} GtkFileFilterFlags;
-
-typedef struct {
- GtkFileFilterFlags contains;
- const gchar *filename;
- const gchar *uri;
- const gchar *display_name;
- const gchar *mime_type;
-} GtkFileFilterInfo;
-
-typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info,
- gpointer data);
-
-typedef void (*GDestroyNotify)(gpointer data);
-
-typedef void (*GCallback)(void);
-
-typedef struct _GClosure GClosure;
-
-typedef void (*GClosureNotify)(gpointer data, GClosure *closure);
-
-typedef enum {
- G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1
-} GConnectFlags;
typedef struct _GThreadFunctions GThreadFunctions;
-/*
- * Converts java.lang.String object to UTF-8 character string.
- */
-const char *getStrFor(JNIEnv *env, jstring value);
-
/**
* Returns :
* NULL if the GLib library is compatible with the given version, or a string
@@ -670,7 +361,7 @@
* Please note that the glib_check_version() is available since 2.6,
* so you should use GLIB_CHECK_VERSION macro instead.
*/
-gchar* (*fp_glib_check_version)(guint required_major, guint required_minor,
+static gchar* (*fp_glib_check_version)(guint required_major, guint required_minor,
guint required_micro);
/**
@@ -680,193 +371,96 @@
#define GLIB_CHECK_VERSION(major, minor, micro) \
(fp_glib_check_version && fp_glib_check_version(major, minor, micro) == NULL)
-/*
- * Check whether the gtk2 library is available and meets the minimum
- * version requirement. If the library is already loaded this method has no
- * effect and returns success.
- * Returns FALSE on failure and TRUE on success.
- */
-gboolean gtk2_check_version();
-
/**
* Returns :
* NULL if the GTK+ library is compatible with the given version, or a string
* describing the version mismatch.
*/
-gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor,
+static gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor,
guint required_micro);
-/*
- * Load the gtk2 library. If the library is already loaded this method has no
- * effect and returns success.
- * Returns FALSE on failure and TRUE on success.
- */
-gboolean gtk2_load(JNIEnv *env);
-/*
- * Loads fp_gtk_show_uri function pointer. This initialization is
- * separated because the function is required only
- * for java.awt.Desktop API. The function relies on initialization in
- * gtk2_load, so it must be invoked only after a successful gtk2_load
- * invocation
- */
-gboolean gtk2_show_uri_load(JNIEnv *env);
+static void gtk2_init(GtkApi* gtk);
-/*
- * Unload the gtk2 library. If the library is already unloaded this method has
- * no effect and returns success.
- * Returns FALSE on failure and TRUE on success.
- */
-gboolean gtk2_unload();
+static void (*fp_g_free)(gpointer mem);
+static void (*fp_g_object_unref)(gpointer object);
+static GdkWindow *(*fp_gdk_get_default_root_window) (void);
-void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height,
- GtkArrowType arrow_type, gboolean fill);
-void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height,
- gint synth_state, GtkTextDirection dir);
-void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height,
- GtkPositionType gap_side, gint gap_x, gint gap_width);
-void gtk2_paint_check(WidgetType widget_type, gint synth_state,
- const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height);
-void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
- const gchar *detail, gint x, gint y, gint width, gint height,
- GtkExpanderStyle expander_style);
-void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height, GtkPositionType gap_side);
-void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height, gboolean has_focus);
-void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
- const char *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height, GtkOrientation orientation);
-void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
- const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_option(WidgetType widget_type, gint synth_state,
- const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height,
- gint synth_state, GtkTextDirection dir);
-void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
- GtkShadowType shadow_type, const gchar *detail,
- gint x, gint y, gint width, gint height, GtkOrientation orientation);
-void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
- const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
- gint x, gint y, gint width, gint height);
+static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf);
+static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
+static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
+static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error);
+static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf);
-void gtk2_init_painting(JNIEnv *env, gint w, gint h);
-gint gtk2_copy_image(gint *dest, gint width, gint height);
-
-gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type);
-gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type);
-gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
- GtkStateType state_type, ColorType color_type);
-jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring key);
-
-GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
- GtkIconSize size, GtkTextDirection direction, const char *detail);
-GdkPixbuf *gtk2_get_icon(const gchar *filename, gint size);
-jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type);
-
-void flush_gtk_event_loop();
-
-jobject gtk2_get_setting(JNIEnv *env, Setting property);
-
-void gtk2_set_range_value(WidgetType widget_type, jdouble value,
- jdouble min, jdouble max, jdouble visible);
-
-void (*fp_g_free)(gpointer mem);
-void (*fp_g_object_unref)(gpointer object);
-GdkWindow *(*fp_gdk_get_default_root_window) (void);
-
-int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf);
-guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
-gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
-GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error);
-GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf);
-
-GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,
+static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,
GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y,
int dest_x, int dest_y, int width, int height);
-GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
+static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
int dest_width, int dest_heigh, GdkInterpType interp_type);
-void (*fp_gtk_widget_destroy)(GtkWidget *widget);
-void (*fp_gtk_window_present)(GtkWindow *window);
-void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
-void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height);
+static void (*fp_gtk_widget_destroy)(void *widget);
+static void (*fp_gtk_window_present)(GtkWindow *window);
+static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
+static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height);
/**
* Function Pointers for GtkFileChooser
*/
-gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
-void (*fp_gtk_widget_hide)(GtkWidget *widget);
-void (*fp_gtk_main_quit)(void);
-GtkWidget* (*fp_gtk_file_chooser_dialog_new)(const gchar *title,
+static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
+static void (*fp_gtk_widget_hide)(void *widget);
+static void (*fp_gtk_main_quit)(void);
+static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title,
GtkWindow *parent, GtkFileChooserAction action,
const gchar *first_button_text, ...);
-gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser,
+static gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser,
const gchar *filename);
-gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
+static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
const char *filename);
-void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
+static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
const gchar *name);
-void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter,
+static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter,
GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data,
GDestroyNotify notify);
-void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
+static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
GtkFileFilter *filter);
-GType (*fp_gtk_file_chooser_get_type)(void);
-GtkFileFilter* (*fp_gtk_file_filter_new)(void);
-void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)(
+static GType (*fp_gtk_file_chooser_get_type)(void);
+static GtkFileFilter* (*fp_gtk_file_filter_new)(void);
+static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)(
GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
-void (*fp_gtk_file_chooser_set_select_multiple)(
+static void (*fp_gtk_file_chooser_set_select_multiple)(
GtkFileChooser *chooser, gboolean select_multiple);
-gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
-GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
-guint (*fp_gtk_g_slist_length)(GSList *list);
-gulong (*fp_g_signal_connect_data)(gpointer instance,
+static gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
+static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
+static guint (*fp_gtk_g_slist_length)(GSList *list);
+static gulong (*fp_g_signal_connect_data)(gpointer instance,
const gchar *detailed_signal, GCallback c_handler, gpointer data,
GClosureNotify destroy_data, GConnectFlags connect_flags);
-void (*fp_gtk_widget_show)(GtkWidget *widget);
-void (*fp_gtk_main)(void);
-guint (*fp_gtk_main_level)(void);
-gchar* (*fp_g_path_get_dirname) (const gchar *file_name);
-XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable);
+static void (*fp_gtk_widget_show)(void *widget);
+static void (*fp_gtk_main)(void);
+static guint (*fp_gtk_main_level)(void);
+static gchar* (*fp_g_path_get_dirname) (const gchar *file_name);
+static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable);
-
-GList* (*fp_g_list_append) (GList *list, gpointer data);
-void (*fp_g_list_free) (GList *list);
-void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
+static GList* (*fp_g_list_append) (GList *list, gpointer data);
+static void (*fp_g_list_free) (GList *list);
+static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
/**
* This function is available for GLIB > 2.20, so it MUST be
* called within GLIB_CHECK_VERSION(2, 20, 0) check.
*/
-gboolean (*fp_g_thread_get_initialized)(void);
+static gboolean (*fp_g_thread_get_initialized)(void);
-void (*fp_g_thread_init)(GThreadFunctions *vtable);
-void (*fp_gdk_threads_init)(void);
-void (*fp_gdk_threads_enter)(void);
-void (*fp_gdk_threads_leave)(void);
+static void (*fp_g_thread_init)(GThreadFunctions *vtable);
+static void (*fp_gdk_threads_init)(void);
+static void (*fp_gdk_threads_enter)(void);
+static void (*fp_gdk_threads_leave)(void);
-gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
+static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
guint32 timestamp, GError **error);
#endif /* !_GTK2_INTERFACE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,2882 @@
+/*
+ * 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
+ * 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.
+ */
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <X11/Xlib.h>
+#include <limits.h>
+#include <string.h>
+#include "gtk3_interface.h"
+#include "java_awt_Transparency.h"
+#include "sizecalc.h"
+#include <jni_util.h>
+#include <stdio.h>
+#include "awt.h"
+
+static void *gtk3_libhandle = NULL;
+
+static jmp_buf j;
+
+/* Widgets */
+static GtkWidget *gtk3_widget = NULL;
+static GtkWidget *gtk3_window = NULL;
+static GtkFixed *gtk3_fixed = NULL;
+static GtkStyleProvider *gtk3_css = NULL;
+
+/* Paint system */
+static cairo_surface_t *surface = NULL;
+static cairo_t *cr = NULL;
+
+static const char ENV_PREFIX[] = "GTK_MODULES=";
+
+static GtkWidget *gtk3_widgets[_GTK_WIDGET_TYPE_SIZE];
+
+static void throw_exception(JNIEnv *env, const char* name, const char* message)
+{
+ jclass class = (*env)->FindClass(env, name);
+
+ if (class != NULL)
+ (*env)->ThrowNew(env, class, message);
+
+ (*env)->DeleteLocalRef(env, class);
+}
+
+static void gtk3_add_state(GtkWidget *widget, GtkStateType state) {
+ GtkStateType old_state = fp_gtk_widget_get_state(widget);
+ fp_gtk_widget_set_state(widget, old_state | state);
+}
+
+static void gtk3_remove_state(GtkWidget *widget, GtkStateType state) {
+ GtkStateType old_state = fp_gtk_widget_get_state(widget);
+ fp_gtk_widget_set_state(widget, old_state & ~state);
+}
+
+/* This is a workaround for the bug:
+ * http://sourceware.org/bugzilla/show_bug.cgi?id=1814
+ * (dlsym/dlopen clears dlerror state)
+ * This bug is specific to Linux, but there is no harm in
+ * applying this workaround on Solaris as well.
+ */
+static void* dl_symbol(const char* name)
+{
+ void* result = dlsym(gtk3_libhandle, name);
+ if (!result)
+ longjmp(j, NO_SYMBOL_EXCEPTION);
+
+ return result;
+}
+
+gboolean gtk3_check(const char* lib_name, int flags)
+{
+ if (gtk3_libhandle != NULL) {
+ /* We've already successfully opened the GTK libs, so return true. */
+ return TRUE;
+ } else {
+ return dlopen(lib_name, flags) != NULL;
+ }
+}
+
+#define ADD_SUPPORTED_ACTION(actionStr) \
+do { \
+ jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, \
+ "Ljava/awt/Desktop$Action;"); \
+ if (!(*env)->ExceptionCheck(env)) { \
+ jobject action = (*env)->GetStaticObjectField(env, cls_action, \
+ fld_action); \
+ (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, \
+ action); \
+ } else { \
+ (*env)->ExceptionClear(env); \
+ } \
+} while(0);
+
+
+static void update_supported_actions(JNIEnv *env) {
+ GVfs * (*fp_g_vfs_get_default) (void);
+ const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);
+ const gchar * const * schemes = NULL;
+
+ jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");
+ CHECK_NULL(cls_action);
+ jclass cls_xDesktopPeer = (*env)->
+ FindClass(env, "sun/awt/X11/XDesktopPeer");
+ CHECK_NULL(cls_xDesktopPeer);
+ jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env,
+ cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");
+ CHECK_NULL(fld_supportedActions);
+ jobject supportedActions = (*env)->GetStaticObjectField(env,
+ cls_xDesktopPeer, fld_supportedActions);
+
+ jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");
+ CHECK_NULL(cls_arrayList);
+ jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add",
+ "(Ljava/lang/Object;)Z");
+ CHECK_NULL(mid_arrayListAdd);
+ jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList,
+ "clear", "()V");
+ CHECK_NULL(mid_arrayListClear);
+
+ (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);
+
+ ADD_SUPPORTED_ACTION("OPEN");
+
+ /**
+ * gtk_show_uri() documentation says:
+ *
+ * > you need to install gvfs to get support for uri schemes such as http://
+ * > or ftp://, as only local files are handled by GIO itself.
+ *
+ * So OPEN action was safely added here.
+ * However, it looks like Solaris 11 have gvfs support only for 32-bit
+ * applications only by default.
+ */
+
+ fp_g_vfs_get_default = dl_symbol("g_vfs_get_default");
+ fp_g_vfs_get_supported_uri_schemes =
+ dl_symbol("g_vfs_get_supported_uri_schemes");
+ dlerror();
+
+ if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) {
+ GVfs * vfs = fp_g_vfs_get_default();
+ schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL;
+ if (schemes) {
+ int i = 0;
+ while (schemes[i]) {
+ if (strcmp(schemes[i], "http") == 0) {
+ ADD_SUPPORTED_ACTION("BROWSE");
+ ADD_SUPPORTED_ACTION("MAIL");
+ break;
+ }
+ i++;
+ }
+ }
+ } else {
+#ifdef DEBUG
+ fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");
+#endif /* DEBUG */
+ }
+
+}
+/**
+ * Functions for awt_Desktop.c
+ */
+static gboolean gtk3_show_uri_load(JNIEnv *env) {
+ gboolean success = FALSE;
+ dlerror();
+ fp_gtk_show_uri = dl_symbol("gtk_show_uri");
+ const char *dlsym_error = dlerror();
+ if (dlsym_error) {
+#ifdef DEBUG
+ fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);
+#endif /* DEBUG */
+ } else if (fp_gtk_show_uri == NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");
+#endif /* DEBUG */
+ } else {
+ gtk->gtk_show_uri = fp_gtk_show_uri;
+ update_supported_actions(env);
+ success = TRUE;
+ }
+ return success;
+}
+
+/**
+ * Functions for sun_awt_X11_GtkFileDialogPeer.c
+ */
+static void gtk3_file_chooser_load()
+{
+ fp_gtk_file_chooser_get_filename = dl_symbol(
+ "gtk_file_chooser_get_filename");
+ fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");
+ fp_gtk_file_chooser_set_current_folder = dl_symbol(
+ "gtk_file_chooser_set_current_folder");
+ fp_gtk_file_chooser_set_filename = dl_symbol(
+ "gtk_file_chooser_set_filename");
+ fp_gtk_file_chooser_set_current_name = dl_symbol(
+ "gtk_file_chooser_set_current_name");
+ fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");
+ fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");
+ fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");
+ fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");
+ fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
+ "gtk_file_chooser_set_do_overwrite_confirmation");
+ fp_gtk_file_chooser_set_select_multiple = dl_symbol(
+ "gtk_file_chooser_set_select_multiple");
+ fp_gtk_file_chooser_get_current_folder = dl_symbol(
+ "gtk_file_chooser_get_current_folder");
+ fp_gtk_file_chooser_get_filenames = dl_symbol(
+ "gtk_file_chooser_get_filenames");
+ fp_gtk_g_slist_length = dl_symbol("g_slist_length");
+ fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_window_get_xid");
+}
+
+static void empty() {}
+
+static gboolean gtk3_version_3_10 = TRUE;
+static gboolean gtk3_version_3_14 = FALSE;
+
+GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
+{
+ gboolean result;
+ int i;
+ int (*handler)();
+ int (*io_handler)();
+ char *gtk_modules_env;
+ gtk3_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);
+ if (gtk3_libhandle == NULL) {
+ return FALSE;
+ }
+
+ if (setjmp(j) == 0)
+ {
+ fp_gtk_check_version = dl_symbol("gtk_check_version");
+
+ /* GLib */
+ fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version");
+ if (!fp_glib_check_version) {
+ dlerror();
+ }
+ fp_g_free = dl_symbol("g_free");
+ fp_g_object_unref = dl_symbol("g_object_unref");
+
+ fp_g_main_context_iteration =
+ dl_symbol("g_main_context_iteration");
+
+ fp_g_value_init = dl_symbol("g_value_init");
+ fp_g_type_is_a = dl_symbol("g_type_is_a");
+ fp_g_value_get_boolean = dl_symbol("g_value_get_boolean");
+ fp_g_value_get_char = dl_symbol("g_value_get_char");
+ fp_g_value_get_uchar = dl_symbol("g_value_get_uchar");
+ fp_g_value_get_int = dl_symbol("g_value_get_int");
+ fp_g_value_get_uint = dl_symbol("g_value_get_uint");
+ fp_g_value_get_long = dl_symbol("g_value_get_long");
+ fp_g_value_get_ulong = dl_symbol("g_value_get_ulong");
+ fp_g_value_get_int64 = dl_symbol("g_value_get_int64");
+ fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64");
+ fp_g_value_get_float = dl_symbol("g_value_get_float");
+ fp_g_value_get_double = dl_symbol("g_value_get_double");
+ fp_g_value_get_string = dl_symbol("g_value_get_string");
+ fp_g_value_get_enum = dl_symbol("g_value_get_enum");
+ fp_g_value_get_flags = dl_symbol("g_value_get_flags");
+ fp_g_value_get_param = dl_symbol("g_value_get_param");
+ fp_g_value_get_boxed = dl_symbol("g_value_get_boxed");
+ fp_g_value_get_pointer = dl_symbol("g_value_get_pointer");
+
+ fp_g_object_get = dl_symbol("g_object_get");
+ fp_g_object_set = dl_symbol("g_object_set");
+
+ fp_g_str_has_prefix = dl_symbol("g_str_has_prefix");
+ fp_g_strsplit = dl_symbol("g_strsplit");
+ fp_g_strfreev = dl_symbol("g_strfreev");
+
+ /* GDK */
+ fp_gdk_get_default_root_window =
+ dl_symbol("gdk_get_default_root_window");
+
+ /* Pixbuf */
+ fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new");
+ fp_gdk_pixbuf_new_from_file =
+ dl_symbol("gdk_pixbuf_new_from_file");
+ fp_gdk_pixbuf_get_from_drawable =
+ dl_symbol("gdk_pixbuf_get_from_window");
+ fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width");
+ fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height");
+ fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels");
+ fp_gdk_pixbuf_get_rowstride =
+ dl_symbol("gdk_pixbuf_get_rowstride");
+ fp_gdk_pixbuf_get_has_alpha =
+ dl_symbol("gdk_pixbuf_get_has_alpha");
+ fp_gdk_pixbuf_get_bits_per_sample =
+ dl_symbol("gdk_pixbuf_get_bits_per_sample");
+ fp_gdk_pixbuf_get_n_channels =
+ dl_symbol("gdk_pixbuf_get_n_channels");
+ fp_gdk_pixbuf_get_colorspace =
+ dl_symbol("gdk_pixbuf_get_colorspace");
+
+ fp_cairo_image_surface_create = dl_symbol("cairo_image_surface_create");
+ fp_cairo_surface_destroy = dl_symbol("cairo_surface_destroy");
+ fp_cairo_create = dl_symbol("cairo_create");
+ fp_cairo_destroy = dl_symbol("cairo_destroy");
+ fp_cairo_fill = dl_symbol("cairo_fill");
+ fp_cairo_rectangle = dl_symbol("cairo_rectangle");
+ fp_cairo_set_source_rgb = dl_symbol("cairo_set_source_rgb");
+ fp_cairo_set_source_rgba = dl_symbol("cairo_set_source_rgba");
+ fp_cairo_surface_flush = dl_symbol("cairo_surface_flush");
+ fp_cairo_paint = dl_symbol("cairo_paint");
+ fp_cairo_clip = dl_symbol("cairo_clip");
+ fp_cairo_image_surface_get_data =
+ dl_symbol("cairo_image_surface_get_data");
+ fp_cairo_image_surface_get_stride =
+ dl_symbol("cairo_image_surface_get_stride");
+
+ fp_gdk_pixbuf_get_from_surface =
+ dl_symbol("gdk_pixbuf_get_from_surface");
+
+ fp_gtk_widget_get_state = dl_symbol("gtk_widget_get_state");
+ fp_gtk_widget_set_state = dl_symbol("gtk_widget_set_state");
+
+ fp_gtk_widget_is_focus = dl_symbol("gtk_widget_is_focus");
+ fp_gtk_widget_set_allocation = dl_symbol("gtk_widget_set_allocation");
+ fp_gtk_widget_get_parent = dl_symbol("gtk_widget_get_parent");
+ fp_gtk_widget_get_window = dl_symbol("gtk_widget_get_window");
+
+ fp_gtk_widget_get_style_context =
+ dl_symbol("gtk_widget_get_style_context");
+ fp_gtk_style_context_get_color =
+ dl_symbol("gtk_style_context_get_color");
+ fp_gtk_style_context_get_background_color =
+ dl_symbol("gtk_style_context_get_background_color");
+ fp_gtk_widget_get_state_flags = dl_symbol("gtk_widget_get_state_flags");
+ fp_gtk_style_context_set_state =
+ dl_symbol("gtk_style_context_set_state");
+ fp_gtk_style_context_add_class =
+ dl_symbol("gtk_style_context_add_class");
+ fp_gtk_style_context_save = dl_symbol("gtk_style_context_save");
+ fp_gtk_style_context_restore = dl_symbol("gtk_style_context_restore");
+ fp_gtk_render_check = dl_symbol("gtk_render_check");
+ fp_gtk_render_option = dl_symbol("gtk_render_option");
+ fp_gtk_render_extension = dl_symbol("gtk_render_extension");
+ fp_gtk_render_expander = dl_symbol("gtk_render_expander");
+ fp_gtk_render_frame_gap = dl_symbol("gtk_render_frame_gap");
+ fp_gtk_render_line = dl_symbol("gtk_render_line");
+ fp_gtk_widget_render_icon_pixbuf =
+ dl_symbol("gtk_widget_render_icon_pixbuf");
+ if (fp_gtk_check_version(3, 10, 0)) {
+ gtk3_version_3_10 = FALSE;
+ } else {
+ fp_gdk_window_create_similar_image_surface =
+ dl_symbol("gdk_window_create_similar_image_surface");
+ }
+ gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0);
+
+ fp_gdk_window_create_similar_surface =
+ dl_symbol("gdk_window_create_similar_surface");
+ fp_gtk_settings_get_for_screen =
+ dl_symbol("gtk_settings_get_for_screen");
+ fp_gtk_widget_get_screen = dl_symbol("gtk_widget_get_screen");
+ fp_gtk_css_provider_get_named = dl_symbol("gtk_css_provider_get_named");
+ fp_gtk_style_context_add_provider =
+ dl_symbol("gtk_style_context_add_provider");
+ fp_gtk_render_frame = dl_symbol("gtk_render_frame");
+ fp_gtk_render_focus = dl_symbol("gtk_render_focus");
+ fp_gtk_render_handle = dl_symbol("gtk_render_handle");
+ fp_gtk_render_arrow = dl_symbol("gtk_render_arrow");
+
+ fp_gtk_style_context_get_property =
+ dl_symbol("gtk_style_context_get_property");
+ fp_gtk_scrolled_window_set_shadow_type =
+ dl_symbol("gtk_scrolled_window_set_shadow_type");
+ fp_gtk_render_slider = dl_symbol("gtk_render_slider");
+ fp_gtk_style_context_get_padding =
+ dl_symbol("gtk_style_context_get_padding");
+ fp_gtk_range_set_inverted = dl_symbol("gtk_range_set_inverted");
+ fp_gtk_style_context_get_font = dl_symbol("gtk_style_context_get_font");
+ fp_gtk_widget_get_allocated_width =
+ dl_symbol("gtk_widget_get_allocated_width");
+ fp_gtk_widget_get_allocated_height =
+ dl_symbol("gtk_widget_get_allocated_height");
+ fp_gtk_icon_theme_get_default = dl_symbol("gtk_icon_theme_get_default");
+ fp_gtk_icon_theme_load_icon = dl_symbol("gtk_icon_theme_load_icon");
+
+ fp_gtk_adjustment_set_lower = dl_symbol("gtk_adjustment_set_lower");
+ fp_gtk_adjustment_set_page_increment =
+ dl_symbol("gtk_adjustment_set_page_increment");
+ fp_gtk_adjustment_set_page_size =
+ dl_symbol("gtk_adjustment_set_page_size");
+ fp_gtk_adjustment_set_step_increment =
+ dl_symbol("gtk_adjustment_set_step_increment");
+ fp_gtk_adjustment_set_upper = dl_symbol("gtk_adjustment_set_upper");
+ fp_gtk_adjustment_set_value = dl_symbol("gtk_adjustment_set_value");
+
+ fp_gtk_render_activity = dl_symbol("gtk_render_activity");
+ fp_gtk_render_background = dl_symbol("gtk_render_background");
+ fp_gtk_style_context_has_class =
+ dl_symbol("gtk_style_context_has_class");
+
+ fp_gtk_style_context_set_junction_sides =
+ dl_symbol("gtk_style_context_set_junction_sides");
+ fp_gtk_style_context_add_region =
+ dl_symbol("gtk_style_context_add_region");
+
+ fp_gtk_init_check = dl_symbol("gtk_init_check");
+
+ /* GTK widgets */
+ fp_gtk_arrow_new = dl_symbol("gtk_arrow_new");
+ fp_gtk_button_new = dl_symbol("gtk_button_new");
+ fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new");
+ fp_gtk_check_button_new = dl_symbol("gtk_check_button_new");
+ fp_gtk_check_menu_item_new =
+ dl_symbol("gtk_check_menu_item_new");
+ fp_gtk_color_selection_dialog_new =
+ dl_symbol("gtk_color_selection_dialog_new");
+ fp_gtk_entry_new = dl_symbol("gtk_entry_new");
+ fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");
+ fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");
+ fp_gtk_image_new = dl_symbol("gtk_image_new");
+ fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new");
+ fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new");
+ fp_gtk_scale_new = dl_symbol("gtk_scale_new");
+ fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");
+ fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");
+ fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new");
+ fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new");
+ fp_gtk_label_new = dl_symbol("gtk_label_new");
+ fp_gtk_menu_new = dl_symbol("gtk_menu_new");
+ fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new");
+ fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new");
+ fp_gtk_menu_item_set_submenu =
+ dl_symbol("gtk_menu_item_set_submenu");
+ fp_gtk_notebook_new = dl_symbol("gtk_notebook_new");
+ fp_gtk_progress_bar_new =
+ dl_symbol("gtk_progress_bar_new");
+ fp_gtk_progress_bar_set_orientation =
+ dl_symbol("gtk_orientable_set_orientation");
+ fp_gtk_radio_button_new =
+ dl_symbol("gtk_radio_button_new");
+ fp_gtk_radio_menu_item_new =
+ dl_symbol("gtk_radio_menu_item_new");
+ fp_gtk_scrolled_window_new =
+ dl_symbol("gtk_scrolled_window_new");
+ fp_gtk_separator_menu_item_new =
+ dl_symbol("gtk_separator_menu_item_new");
+ fp_gtk_text_view_new = dl_symbol("gtk_text_view_new");
+ fp_gtk_toggle_button_new =
+ dl_symbol("gtk_toggle_button_new");
+ fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new");
+ fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new");
+ fp_gtk_viewport_new = dl_symbol("gtk_viewport_new");
+ fp_gtk_window_new = dl_symbol("gtk_window_new");
+ fp_gtk_window_present = dl_symbol("gtk_window_present");
+ fp_gtk_window_move = dl_symbol("gtk_window_move");
+ fp_gtk_window_resize = dl_symbol("gtk_window_resize");
+
+ fp_gtk_dialog_new = dl_symbol("gtk_dialog_new");
+ fp_gtk_frame_new = dl_symbol("gtk_frame_new");
+
+ fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new");
+ fp_gtk_container_add = dl_symbol("gtk_container_add");
+ fp_gtk_menu_shell_append =
+ dl_symbol("gtk_menu_shell_append");
+ fp_gtk_widget_realize = dl_symbol("gtk_widget_realize");
+ fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy");
+ fp_gtk_widget_render_icon =
+ dl_symbol("gtk_widget_render_icon");
+ fp_gtk_widget_set_name =
+ dl_symbol("gtk_widget_set_name");
+ fp_gtk_widget_set_parent =
+ dl_symbol("gtk_widget_set_parent");
+ fp_gtk_widget_set_direction =
+ dl_symbol("gtk_widget_set_direction");
+ fp_gtk_widget_style_get =
+ dl_symbol("gtk_widget_style_get");
+ fp_gtk_widget_class_install_style_property =
+ dl_symbol("gtk_widget_class_install_style_property");
+ fp_gtk_widget_class_find_style_property =
+ dl_symbol("gtk_widget_class_find_style_property");
+ fp_gtk_widget_style_get_property =
+ dl_symbol("gtk_widget_style_get_property");
+ fp_pango_font_description_to_string =
+ dl_symbol("pango_font_description_to_string");
+ fp_gtk_settings_get_default =
+ dl_symbol("gtk_settings_get_default");
+ fp_gtk_widget_get_settings =
+ dl_symbol("gtk_widget_get_settings");
+ fp_gtk_border_get_type = dl_symbol("gtk_border_get_type");
+ fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");
+ fp_gtk_widget_size_request =
+ dl_symbol("gtk_widget_size_request");
+ fp_gtk_range_get_adjustment =
+ dl_symbol("gtk_range_get_adjustment");
+
+ fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");
+ fp_gtk_main_quit = dl_symbol("gtk_main_quit");
+ fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");
+ fp_gtk_widget_show = dl_symbol("gtk_widget_show");
+ fp_gtk_main = dl_symbol("gtk_main");
+
+ fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");
+
+ fp_gdk_threads_enter = ∅
+ fp_gdk_threads_leave = ∅
+
+ /**
+ * Functions for sun_awt_X11_GtkFileDialogPeer.c
+ */
+ gtk3_file_chooser_load();
+
+ fp_gtk_combo_box_new = dlsym(gtk3_libhandle, "gtk_combo_box_new");
+ fp_gtk_combo_box_entry_new = dlsym(gtk3_libhandle,
+ "gtk_combo_box_new_with_entry");
+ fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle,
+ "gtk_separator_tool_item_new");
+
+ fp_g_list_append = dl_symbol("g_list_append");
+ fp_g_list_free = dl_symbol("g_list_free");
+ fp_g_list_free_full = dl_symbol("g_list_free_full");
+ }
+ /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION
+ * Otherwise we can check the return value of setjmp method.
+ */
+ else
+ {
+ dlclose(gtk3_libhandle);
+ gtk3_libhandle = NULL;
+
+ return NULL;
+ }
+
+ /*
+ * Strip the AT-SPI GTK_MODULEs if present
+ */
+ gtk_modules_env = getenv ("GTK_MODULES");
+ if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") ||
+ gtk_modules_env && strstr (gtk_modules_env, "gail"))
+ {
+ /* the new env will be smaller than the old one */
+ gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc,
+ sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env));
+
+ if (new_env != NULL )
+ {
+ /* careful, strtok modifies its args */
+ gchar *tmp_env = strdup (gtk_modules_env);
+ strcpy(new_env, ENV_PREFIX);
+
+ /* strip out 'atk-bridge' and 'gail' */
+ size_t PREFIX_LENGTH = strlen(ENV_PREFIX);
+ while (s = strtok(tmp_env, ":"))
+ {
+ if ((!strstr (s, "atk-bridge")) && (!strstr (s, "gail")))
+ {
+ if (strlen (new_env) > PREFIX_LENGTH) {
+ new_env = strcat (new_env, ":");
+ }
+ new_env = strcat(new_env, s);
+ }
+ if (tmp_env)
+ {
+ free (tmp_env);
+ tmp_env = NULL; /* next call to strtok arg1==NULL */
+ }
+ }
+ putenv (new_env);
+ free (new_env);
+ free (tmp_env);
+ }
+ }
+ /*
+ * GTK should be initialized with gtk_init_check() before use.
+ *
+ * gtk_init_check installs its own error handlers. It is critical that
+ * we preserve error handler set from AWT. Otherwise we'll crash on
+ * BadMatch errors which we would normally ignore. The IO error handler
+ * is preserved here, too, just for consistency.
+ */
+ AWT_LOCK();
+ handler = XSetErrorHandler(NULL);
+ io_handler = XSetIOErrorHandler(NULL);
+ result = (*fp_gtk_init_check)(NULL, NULL);
+ XSetErrorHandler(handler);
+ XSetIOErrorHandler(io_handler);
+ AWT_UNLOCK();
+ /* Initialize widget array. */
+ for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
+ {
+ gtk3_widgets[i] = NULL;
+ }
+ if (result) {
+ GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));
+ gtk3_init(gtk);
+ return gtk;
+ }
+ return NULL;
+}
+
+static int gtk3_unload()
+{
+ int i;
+ char *gtk3_error;
+
+ if (!gtk3_libhandle)
+ return TRUE;
+
+ /* Release painting objects */
+ if (surface != NULL) {
+ fp_cairo_destroy(cr);
+ fp_cairo_surface_destroy(surface);
+ surface = NULL;
+ }
+
+ if (gtk3_window != NULL) {
+ /* Destroying toplevel widget will destroy all contained widgets */
+ (*fp_gtk_widget_destroy)(gtk3_window);
+
+ /* Unset some static data so they get reinitialized on next load */
+ gtk3_window = NULL;
+ }
+
+ dlerror();
+ dlclose(gtk3_libhandle);
+ if ((gtk3_error = dlerror()) != NULL)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Dispatch all pending events from the GTK event loop.
+ * This is needed to catch theme change and update widgets' style.
+ */
+static void flush_gtk_event_loop()
+{
+ while((*fp_g_main_context_iteration)(NULL));
+}
+
+/*
+ * Initialize components of containment hierarchy. This creates a GtkFixed
+ * inside a GtkWindow. All widgets get realized.
+ */
+static void init_containers()
+{
+ if (gtk3_window == NULL)
+ {
+ gtk3_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
+ gtk3_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();
+ (*fp_gtk_container_add)((GtkContainer*)gtk3_window,
+ (GtkWidget *)gtk3_fixed);
+ (*fp_gtk_widget_realize)(gtk3_window);
+ (*fp_gtk_widget_realize)((GtkWidget *)gtk3_fixed);
+
+ GtkSettings* settings = fp_gtk_settings_get_for_screen(
+ fp_gtk_widget_get_screen(gtk3_window));
+ gchar* strval = NULL;
+ fp_g_object_get(settings, "gtk-theme-name", &strval, NULL);
+ gtk3_css = fp_gtk_css_provider_get_named(strval, NULL);
+ }
+}
+
+/*
+ * Ensure everything is ready for drawing an element of the specified width
+ * and height.
+ *
+ * We should somehow handle translucent images. GTK can draw to X Drawables
+ * only, which don't support alpha. When we retrieve the image back from
+ * the server, translucency information is lost. There're several ways to
+ * work around this:
+ * 1) Subclass GdkPixmap and cache translucent objects on client side. This
+ * requires us to implement parts of X server drawing logic on client side.
+ * Many X requests can potentially be "translucent"; e.g. XDrawLine with
+ * fill=tile and a translucent tile is a "translucent" operation, whereas
+ * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some
+ * do) intermix transparent and opaque operations which makes caching even
+ * more problematic.
+ * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support
+ * for it (as of version 2.6). Also even in JDS 3 Xorg does not support
+ * these visuals by default, which makes optimizing for them pointless.
+ * We can consider doing this at a later point when ARGB visuals become more
+ * popular.
+ * 3') GTK has plans to use Cairo as its graphical backend (presumably in
+ * 2.8), and Cairo supports alpha. With it we could also get rid of the
+ * unnecessary round trip to server and do all the drawing on client side.
+ * 4) For now we draw to two different pixmaps and restore alpha channel by
+ * comparing results. This can be optimized by using subclassed pixmap and
+*/
+static void gtk3_init_painting(JNIEnv *env, gint width, gint height)
+{
+ init_containers();
+
+ if (cr) {
+ fp_cairo_destroy(cr);
+ }
+
+ if (surface != NULL) {
+ /* free old stuff */
+ fp_cairo_surface_destroy(surface);
+
+ }
+
+ if (gtk3_version_3_10) {
+ surface = fp_gdk_window_create_similar_image_surface(
+ fp_gtk_widget_get_window(gtk3_window),
+ CAIRO_FORMAT_ARGB32, width, height, 1);
+ } else {
+ surface = fp_cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ width, height);
+ }
+
+ cr = fp_cairo_create(surface);
+}
+
+/*
+ * Restore image from white and black pixmaps and copy it into destination
+ * buffer. This method compares two pixbufs taken from white and black
+ * pixmaps and decodes color and alpha components. Pixbufs are RGB without
+ * alpha, destination buffer is ABGR.
+ *
+ * The return value is the transparency type of the resulting image, either
+ * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
+ * java_awt_Transparency_TRANSLUCENT.
+ */
+static gint gtk3_copy_image(gint *dst, gint width, gint height)
+{
+ gint i, j, r, g, b;
+ guchar *data;
+ gint stride, padding;
+
+ fp_cairo_surface_flush(surface);
+ data = (*fp_cairo_image_surface_get_data)(surface);
+ stride = (*fp_cairo_image_surface_get_stride)(surface);
+ padding = stride - width * 4;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ int r = *data++;
+ int g = *data++;
+ int b = *data++;
+ int a = *data++;
+ *dst++ = (a << 24 | b << 16 | g << 8 | r);
+ }
+ data += padding;
+ }
+ return java_awt_Transparency_TRANSLUCENT;
+}
+
+static void gtk3_set_direction(GtkWidget *widget, GtkTextDirection dir)
+{
+ /*
+ * Some engines (inexplicably) look at the direction of the widget's
+ * parent, so we need to set the direction of both the widget and its
+ * parent.
+ */
+ (*fp_gtk_widget_set_direction)(widget, dir);
+ GtkWidget* parent = fp_gtk_widget_get_parent(widget);
+ if (parent != NULL) {
+ fp_gtk_widget_set_direction(parent, dir);
+ }
+}
+
+/* GTK state_type filter */
+static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state)
+{
+ GtkStateType result = GTK_STATE_NORMAL;
+
+ if ((synth_state & DISABLED) != 0) {
+ result = GTK_STATE_INSENSITIVE;
+ } else if ((synth_state & PRESSED) != 0) {
+ result = GTK_STATE_ACTIVE;
+ } else if ((synth_state & MOUSE_OVER) != 0) {
+ result = GTK_STATE_PRELIGHT;
+ }
+ return result;
+}
+
+static GtkStateFlags get_gtk_state_flags(gint synth_state)
+{
+ GtkStateFlags flags = 0;
+
+ if ((synth_state & DISABLED) != 0) {
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+ }
+ if (((synth_state & PRESSED) != 0 || (synth_state & SELECTED) != 0)) {
+ flags |= GTK_STATE_FLAG_ACTIVE;
+ }
+ if ((synth_state & MOUSE_OVER) != 0) {
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ }
+ if ((synth_state & FOCUSED) != 0) {
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ }
+ return flags;
+}
+
+static GtkStateFlags get_gtk_flags(GtkStateType state_type) {
+ GtkStateFlags flags = 0;
+ switch (state_type)
+ {
+ case GTK_STATE_PRELIGHT:
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ break;
+ case GTK_STATE_SELECTED:
+ flags |= GTK_STATE_FLAG_SELECTED;
+ break;
+ case GTK_STATE_INSENSITIVE:
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+ break;
+ case GTK_STATE_ACTIVE:
+ flags |= GTK_STATE_FLAG_ACTIVE;
+ break;
+ case GTK_STATE_FOCUSED:
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ break;
+ default:
+ break;
+ }
+ return flags;
+}
+
+/* GTK shadow_type filter */
+static GtkShadowType get_gtk_shadow_type(WidgetType widget_type,
+ gint synth_state)
+{
+ GtkShadowType result = GTK_SHADOW_OUT;
+
+ if ((synth_state & SELECTED) != 0) {
+ result = GTK_SHADOW_IN;
+ }
+ return result;
+}
+
+
+static GtkWidget* gtk3_get_arrow(GtkArrowType arrow_type,
+ GtkShadowType shadow_type)
+{
+ GtkWidget *arrow = NULL;
+ if (NULL == gtk3_widgets[_GTK_ARROW_TYPE])
+ {
+ gtk3_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type,
+ shadow_type);
+ (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed,
+ gtk3_widgets[_GTK_ARROW_TYPE]);
+ (*fp_gtk_widget_realize)(gtk3_widgets[_GTK_ARROW_TYPE]);
+ }
+ arrow = gtk3_widgets[_GTK_ARROW_TYPE];
+
+ (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type);
+ return arrow;
+}
+
+static GtkAdjustment* create_adjustment()
+{
+ return (GtkAdjustment *)
+ (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0);
+}
+
+/**
+ * Returns a pointer to the cached native widget for the specified widget
+ * type.
+ */
+static GtkWidget *gtk3_get_widget(WidgetType widget_type)
+{
+ gboolean init_result = FALSE;
+ GtkWidget *result = NULL;
+ switch (widget_type)
+ {
+ case BUTTON:
+ case TABLE_HEADER:
+ if (init_result = (NULL == gtk3_widgets[_GTK_BUTTON_TYPE]))
+ {
+ gtk3_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)();
+ }
+ result = gtk3_widgets[_GTK_BUTTON_TYPE];
+ break;
+ case CHECK_BOX:
+ if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]))
+ {
+ gtk3_widgets[_GTK_CHECK_BUTTON_TYPE] =
+ (*fp_gtk_check_button_new)();
+ }
+ result = gtk3_widgets[_GTK_CHECK_BUTTON_TYPE];
+ break;
+ case CHECK_BOX_MENU_ITEM:
+ if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))
+ {
+ gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE] =
+ (*fp_gtk_check_menu_item_new)();
+ }
+ result = gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE];
+ break;
+ /************************************************************
+ * Creation a dedicated color chooser is dangerous because
+ * it deadlocks the EDT
+ ************************************************************/
+/* case COLOR_CHOOSER:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))
+ {
+ gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =
+ (*fp_gtk_color_selection_dialog_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];
+ break;*/
+ case COMBO_BOX:
+ if (init_result = (NULL == gtk3_widgets[_GTK_COMBO_BOX_TYPE]))
+ {
+ gtk3_widgets[_GTK_COMBO_BOX_TYPE] =
+ (*fp_gtk_combo_box_new)();
+ }
+ result = gtk3_widgets[_GTK_COMBO_BOX_TYPE];
+ break;
+ case COMBO_BOX_ARROW_BUTTON:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))
+ {
+ gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] =
+ (*fp_gtk_toggle_button_new)();
+ }
+ result = gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE];
+ break;
+ case COMBO_BOX_TEXT_FIELD:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))
+ {
+ result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] =
+ (*fp_gtk_entry_new)();
+ }
+ result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE];
+ break;
+ case DESKTOP_ICON:
+ case INTERNAL_FRAME_TITLE_PANE:
+ case LABEL:
+ if (init_result = (NULL == gtk3_widgets[_GTK_LABEL_TYPE]))
+ {
+ gtk3_widgets[_GTK_LABEL_TYPE] =
+ (*fp_gtk_label_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_LABEL_TYPE];
+ break;
+ case DESKTOP_PANE:
+ case PANEL:
+ case ROOT_PANE:
+ if (init_result = (NULL == gtk3_widgets[_GTK_CONTAINER_TYPE]))
+ {
+ /* There is no constructor for a container type. I've
+ * chosen GtkFixed container since it has a default
+ * constructor.
+ */
+ gtk3_widgets[_GTK_CONTAINER_TYPE] =
+ (*fp_gtk_fixed_new)();
+ }
+ result = gtk3_widgets[_GTK_CONTAINER_TYPE];
+ break;
+ case EDITOR_PANE:
+ case TEXT_AREA:
+ case TEXT_PANE:
+ if (init_result = (NULL == gtk3_widgets[_GTK_TEXT_VIEW_TYPE]))
+ {
+ gtk3_widgets[_GTK_TEXT_VIEW_TYPE] =
+ (*fp_gtk_text_view_new)();
+ }
+ result = gtk3_widgets[_GTK_TEXT_VIEW_TYPE];
+ break;
+ case FORMATTED_TEXT_FIELD:
+ case PASSWORD_FIELD:
+ case TEXT_FIELD:
+ if (init_result = (NULL == gtk3_widgets[_GTK_ENTRY_TYPE]))
+ {
+ gtk3_widgets[_GTK_ENTRY_TYPE] =
+ (*fp_gtk_entry_new)();
+ }
+ result = gtk3_widgets[_GTK_ENTRY_TYPE];
+ break;
+ case HANDLE_BOX:
+ if (init_result = (NULL == gtk3_widgets[_GTK_HANDLE_BOX_TYPE]))
+ {
+ gtk3_widgets[_GTK_HANDLE_BOX_TYPE] =
+ (*fp_gtk_handle_box_new)();
+ }
+ result = gtk3_widgets[_GTK_HANDLE_BOX_TYPE];
+ break;
+ case HSCROLL_BAR:
+ case HSCROLL_BAR_BUTTON_LEFT:
+ case HSCROLL_BAR_BUTTON_RIGHT:
+ case HSCROLL_BAR_TRACK:
+ case HSCROLL_BAR_THUMB:
+ if (init_result = (NULL == gtk3_widgets[_GTK_HSCROLLBAR_TYPE]))
+ {
+ gtk3_widgets[_GTK_HSCROLLBAR_TYPE] =
+ (*fp_gtk_hscrollbar_new)(create_adjustment());
+ }
+ result = gtk3_widgets[_GTK_HSCROLLBAR_TYPE];
+ break;
+ case HSEPARATOR:
+ if (init_result = (NULL == gtk3_widgets[_GTK_HSEPARATOR_TYPE]))
+ {
+ gtk3_widgets[_GTK_HSEPARATOR_TYPE] =
+ (*fp_gtk_hseparator_new)();
+ }
+ result = gtk3_widgets[_GTK_HSEPARATOR_TYPE];
+ break;
+ case HSLIDER:
+ case HSLIDER_THUMB:
+ case HSLIDER_TRACK:
+ if (init_result = (NULL == gtk3_widgets[_GTK_HSCALE_TYPE]))
+ {
+ gtk3_widgets[_GTK_HSCALE_TYPE] =
+ (*fp_gtk_scale_new)(GTK_ORIENTATION_HORIZONTAL, NULL);
+ }
+ result = gtk3_widgets[_GTK_HSCALE_TYPE];
+ break;
+ case HSPLIT_PANE_DIVIDER:
+ case SPLIT_PANE:
+ if (init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE]))
+ {
+ gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)();
+ }
+ result = gtk3_widgets[_GTK_HPANED_TYPE];
+ break;
+ case IMAGE:
+ if (init_result = (NULL == gtk3_widgets[_GTK_IMAGE_TYPE]))
+ {
+ gtk3_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)();
+ }
+ result = gtk3_widgets[_GTK_IMAGE_TYPE];
+ break;
+ case INTERNAL_FRAME:
+ if (init_result = (NULL == gtk3_widgets[_GTK_WINDOW_TYPE]))
+ {
+ gtk3_widgets[_GTK_WINDOW_TYPE] =
+ (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
+ }
+ result = gtk3_widgets[_GTK_WINDOW_TYPE];
+ break;
+ case TOOL_TIP:
+ if (init_result = (NULL == gtk3_widgets[_GTK_TOOLTIP_TYPE]))
+ {
+ result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
+ gtk3_widgets[_GTK_TOOLTIP_TYPE] = result;
+ }
+ result = gtk3_widgets[_GTK_TOOLTIP_TYPE];
+ break;
+ case LIST:
+ case TABLE:
+ case TREE:
+ case TREE_CELL:
+ if (init_result = (NULL == gtk3_widgets[_GTK_TREE_VIEW_TYPE]))
+ {
+ gtk3_widgets[_GTK_TREE_VIEW_TYPE] =
+ (*fp_gtk_tree_view_new)();
+ }
+ result = gtk3_widgets[_GTK_TREE_VIEW_TYPE];
+ break;
+ case TITLED_BORDER:
+ if (init_result = (NULL == gtk3_widgets[_GTK_FRAME_TYPE]))
+ {
+ gtk3_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL);
+ }
+ result = gtk3_widgets[_GTK_FRAME_TYPE];
+ break;
+ case POPUP_MENU:
+ if (init_result = (NULL == gtk3_widgets[_GTK_MENU_TYPE]))
+ {
+ gtk3_widgets[_GTK_MENU_TYPE] =
+ (*fp_gtk_menu_new)();
+ }
+ result = gtk3_widgets[_GTK_MENU_TYPE];
+ break;
+ case MENU:
+ case MENU_ITEM:
+ case MENU_ITEM_ACCELERATOR:
+ if (init_result = (NULL == gtk3_widgets[_GTK_MENU_ITEM_TYPE]))
+ {
+ gtk3_widgets[_GTK_MENU_ITEM_TYPE] =
+ (*fp_gtk_menu_item_new)();
+ }
+ result = gtk3_widgets[_GTK_MENU_ITEM_TYPE];
+ break;
+ case MENU_BAR:
+ if (init_result = (NULL == gtk3_widgets[_GTK_MENU_BAR_TYPE]))
+ {
+ gtk3_widgets[_GTK_MENU_BAR_TYPE] =
+ (*fp_gtk_menu_bar_new)();
+ }
+ result = gtk3_widgets[_GTK_MENU_BAR_TYPE];
+ break;
+ case COLOR_CHOOSER:
+ case OPTION_PANE:
+ if (init_result = (NULL == gtk3_widgets[_GTK_DIALOG_TYPE]))
+ {
+ gtk3_widgets[_GTK_DIALOG_TYPE] =
+ (*fp_gtk_dialog_new)();
+ }
+ result = gtk3_widgets[_GTK_DIALOG_TYPE];
+ break;
+ case POPUP_MENU_SEPARATOR:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))
+ {
+ gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] =
+ (*fp_gtk_separator_menu_item_new)();
+ }
+ result = gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE];
+ break;
+ case HPROGRESS_BAR:
+ if (init_result = (NULL == gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]))
+ {
+ gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE] =
+ (*fp_gtk_progress_bar_new)();
+ }
+ result = gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE];
+ break;
+ case VPROGRESS_BAR:
+ if (init_result = (NULL == gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]))
+ {
+ gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE] =
+ (*fp_gtk_progress_bar_new)();
+ /*
+ * Vertical JProgressBars always go bottom-to-top,
+ * regardless of the ComponentOrientation.
+ */
+ (*fp_gtk_progress_bar_set_orientation)(
+ (GtkProgressBar *)gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE],
+ GTK_PROGRESS_BOTTOM_TO_TOP);
+ }
+ result = gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE];
+ break;
+ case RADIO_BUTTON:
+ if (init_result = (NULL == gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]))
+ {
+ gtk3_widgets[_GTK_RADIO_BUTTON_TYPE] =
+ (*fp_gtk_radio_button_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_RADIO_BUTTON_TYPE];
+ break;
+ case RADIO_BUTTON_MENU_ITEM:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))
+ {
+ gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE] =
+ (*fp_gtk_radio_menu_item_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE];
+ break;
+ case SCROLL_PANE:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]))
+ {
+ gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE] =
+ (*fp_gtk_scrolled_window_new)(NULL, NULL);
+ }
+ result = gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE];
+ break;
+ case SPINNER:
+ case SPINNER_ARROW_BUTTON:
+ case SPINNER_TEXT_FIELD:
+ if (init_result = (NULL == gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]))
+ {
+ result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE] =
+ (*fp_gtk_spin_button_new)(NULL, 0, 0);
+ }
+ result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE];
+ break;
+ case TABBED_PANE:
+ case TABBED_PANE_TAB_AREA:
+ case TABBED_PANE_CONTENT:
+ case TABBED_PANE_TAB:
+ if (init_result = (NULL == gtk3_widgets[_GTK_NOTEBOOK_TYPE]))
+ {
+ gtk3_widgets[_GTK_NOTEBOOK_TYPE] =
+ (*fp_gtk_notebook_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_NOTEBOOK_TYPE];
+ break;
+ case TOGGLE_BUTTON:
+ if (init_result = (NULL == gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]))
+ {
+ gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE] =
+ (*fp_gtk_toggle_button_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE];
+ break;
+ case TOOL_BAR:
+ case TOOL_BAR_DRAG_WINDOW:
+ if (init_result = (NULL == gtk3_widgets[_GTK_TOOLBAR_TYPE]))
+ {
+ gtk3_widgets[_GTK_TOOLBAR_TYPE] =
+ (*fp_gtk_toolbar_new)(NULL);
+ }
+ result = gtk3_widgets[_GTK_TOOLBAR_TYPE];
+ break;
+ case TOOL_BAR_SEPARATOR:
+ if (init_result =
+ (NULL == gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))
+ {
+ gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] =
+ (*fp_gtk_separator_tool_item_new)();
+ }
+ result = gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE];
+ break;
+ case VIEWPORT:
+ if (init_result = (NULL == gtk3_widgets[_GTK_VIEWPORT_TYPE]))
+ {
+ GtkAdjustment *adjustment = create_adjustment();
+ gtk3_widgets[_GTK_VIEWPORT_TYPE] =
+ (*fp_gtk_viewport_new)(adjustment, adjustment);
+ }
+ result = gtk3_widgets[_GTK_VIEWPORT_TYPE];
+ break;
+ case VSCROLL_BAR:
+ case VSCROLL_BAR_BUTTON_UP:
+ case VSCROLL_BAR_BUTTON_DOWN:
+ case VSCROLL_BAR_TRACK:
+ case VSCROLL_BAR_THUMB:
+ if (init_result = (NULL == gtk3_widgets[_GTK_VSCROLLBAR_TYPE]))
+ {
+ gtk3_widgets[_GTK_VSCROLLBAR_TYPE] =
+ (*fp_gtk_vscrollbar_new)(create_adjustment());
+ }
+ result = gtk3_widgets[_GTK_VSCROLLBAR_TYPE];
+ break;
+ case VSEPARATOR:
+ if (init_result = (NULL == gtk3_widgets[_GTK_VSEPARATOR_TYPE]))
+ {
+ gtk3_widgets[_GTK_VSEPARATOR_TYPE] =
+ (*fp_gtk_vseparator_new)();
+ }
+ result = gtk3_widgets[_GTK_VSEPARATOR_TYPE];
+ break;
+ case VSLIDER:
+ case VSLIDER_THUMB:
+ case VSLIDER_TRACK:
+ if (init_result = (NULL == gtk3_widgets[_GTK_VSCALE_TYPE]))
+ {
+ gtk3_widgets[_GTK_VSCALE_TYPE] =
+ (*fp_gtk_scale_new)(GTK_ORIENTATION_VERTICAL, NULL);
+ }
+ result = gtk3_widgets[_GTK_VSCALE_TYPE];
+ /*
+ * Vertical JSliders start at the bottom, while vertical
+ * GtkVScale widgets start at the top (by default), so to fix
+ * this we set the "inverted" flag to get the Swing behavior.
+ */
+ fp_gtk_range_set_inverted((GtkRange*)result, TRUE);
+ break;
+ case VSPLIT_PANE_DIVIDER:
+ if (init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE]))
+ {
+ gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)();
+ }
+ result = gtk3_widgets[_GTK_VPANED_TYPE];
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+
+ if (result != NULL && init_result)
+ {
+ if (widget_type == RADIO_BUTTON_MENU_ITEM ||
+ widget_type == CHECK_BOX_MENU_ITEM ||
+ widget_type == MENU_ITEM ||
+ widget_type == MENU ||
+ widget_type == POPUP_MENU_SEPARATOR)
+ {
+ GtkWidget *menu = gtk3_get_widget(POPUP_MENU);
+ (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result);
+ }
+ else if (widget_type == POPUP_MENU)
+ {
+ GtkWidget *menu_bar = gtk3_get_widget(MENU_BAR);
+ GtkWidget *root_menu = (*fp_gtk_menu_item_new)();
+ (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result);
+ (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu);
+ }
+ else if (widget_type == COMBO_BOX_TEXT_FIELD )
+ {
+ GtkWidget* combo = gtk3_get_widget(COMBO_BOX);
+
+ /*
+ * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry
+ * in order to trick engines into thinking it's a real combobox
+ * arrow button/text field.
+ */
+
+ fp_gtk_container_add ((GtkContainer*)(combo), result);
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (combo);
+ fp_gtk_style_context_add_class (context, "combobox-entry");
+ context = fp_gtk_widget_get_style_context (result);
+ fp_gtk_style_context_add_class (context, "combobox");
+ fp_gtk_style_context_add_class (context, "entry");
+ }
+ else if (widget_type == COMBO_BOX_ARROW_BUTTON )
+ {
+ GtkWidget* combo = gtk3_get_widget(COMBO_BOX);
+ fp_gtk_widget_set_parent(result, combo);
+ }
+ else if (widget_type != TOOL_TIP &&
+ widget_type != INTERNAL_FRAME &&
+ widget_type != OPTION_PANE)
+ {
+ (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, result);
+ }
+ (*fp_gtk_widget_realize)(result);
+ }
+ return result;
+}
+
+static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ GtkArrowType arrow_type, gboolean fill)
+{
+ gdouble xx, yy, a = G_PI;
+ int s = width;
+ gtk3_widget = gtk3_get_arrow(arrow_type, shadow_type);
+
+ switch (widget_type)
+ {
+ case SPINNER_ARROW_BUTTON:
+ s = (int)(0.4 * width + 0.5) + 1;
+ if (arrow_type == GTK_ARROW_UP) {
+ a = 0;
+ } else if (arrow_type == GTK_ARROW_DOWN) {
+ a = G_PI;
+ }
+ break;
+
+ case HSCROLL_BAR_BUTTON_LEFT:
+ s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1;
+ a = 3 * G_PI / 2;
+ break;
+
+ case HSCROLL_BAR_BUTTON_RIGHT:
+ s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1;
+ a = G_PI / 2;
+ break;
+
+ case VSCROLL_BAR_BUTTON_UP:
+ s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1;
+ a = 0;
+ break;
+
+ case VSCROLL_BAR_BUTTON_DOWN:
+ s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1;
+ a = G_PI;
+ break;
+
+ case COMBO_BOX_ARROW_BUTTON:
+ s = (int)(0.3 * height + 0.5) + 1;
+ a = G_PI;
+ break;
+
+ case TABLE:
+ s = (int)(0.8 * height + 0.5) + 1;
+ if (arrow_type == GTK_ARROW_UP) {
+ a = G_PI;
+ } else if (arrow_type == GTK_ARROW_DOWN) {
+ a = 0;
+ }
+ break;
+
+ case MENU_ITEM:
+ if (arrow_type == GTK_ARROW_UP) {
+ a = G_PI;
+ } else if (arrow_type == GTK_ARROW_DOWN) {
+ a = 0;
+ } else if (arrow_type == GTK_ARROW_RIGHT) {
+ a = G_PI / 2;
+ } else if (arrow_type == GTK_ARROW_LEFT) {
+ a = 3 * G_PI / 2;
+ }
+ break;
+
+ default:
+ if (arrow_type == GTK_ARROW_UP) {
+ a = G_PI;
+ } else if (arrow_type == GTK_ARROW_DOWN) {
+ a = 0;
+ } else if (arrow_type == GTK_ARROW_RIGHT) {
+ a = G_PI / 2;
+ } else if (arrow_type == GTK_ARROW_LEFT) {
+ a = 3 * G_PI / 2;
+ }
+ break;
+ }
+
+ if (s < width && s < height) {
+ xx = x + (0.5 * (width - s) + 0.5);
+ yy = y + (0.5 * (height - s) + 0.5);
+ } else {
+ xx = x;
+ yy = y;
+ }
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ fp_gtk_style_context_save (context);
+
+
+ if (detail != NULL) {
+ transform_detail_string(detail, context);
+ }
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+
+ fp_gtk_style_context_set_state (context, flags);
+
+ (*fp_gtk_render_arrow)(context, cr, a, xx, yy, s);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_box(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ gint synth_state, GtkTextDirection dir)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ if (widget_type == HSLIDER_TRACK) {
+ /*
+ * For horizontal JSliders with right-to-left orientation, we need
+ * to set the "inverted" flag to match the native GTK behavior where
+ * the foreground highlight is on the right side of the slider thumb.
+ * This is needed especially for the ubuntulooks engine, which looks
+ * exclusively at the "inverted" flag to determine on which side of
+ * the thumb to paint the highlight...
+ */
+ fp_gtk_range_set_inverted((GtkRange*)gtk3_widget, dir ==
+ GTK_TEXT_DIR_RTL);
+
+ /*
+ * Note however that other engines like clearlooks will look at both
+ * the "inverted" field and the text direction to determine how
+ * the foreground highlight is painted:
+ * !inverted && ltr --> paint highlight on left side
+ * !inverted && rtl --> paint highlight on right side
+ * inverted && ltr --> paint highlight on right side
+ * inverted && rtl --> paint highlight on left side
+ * So the only way to reliably get the desired results for horizontal
+ * JSlider (i.e., highlight on left side for LTR ComponentOrientation
+ * and highlight on right side for RTL ComponentOrientation) is to
+ * always override text direction as LTR, and then set the "inverted"
+ * flag accordingly (as we have done above).
+ */
+ dir = GTK_TEXT_DIR_LTR;
+ }
+
+ /*
+ * Some engines (e.g. clearlooks) will paint the shadow of certain
+ * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the
+ * the text direction.
+ */
+ gtk3_set_direction(gtk3_widget, dir);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ fp_gtk_style_context_save (context);
+
+ transform_detail_string(detail, context);
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+
+ if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) {
+ flags |= GTK_STATE_FLAG_ACTIVE;
+ }
+
+ if (synth_state & MOUSE_OVER) {
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ }
+
+ if (synth_state & FOCUSED) {
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ }
+
+ if (synth_state & DEFAULT) {
+ fp_gtk_style_context_add_class (context, "default");
+ }
+
+ fp_gtk_style_context_set_state (context, flags);
+
+ if (fp_gtk_style_context_has_class(context, "progressbar")) {
+ fp_gtk_render_activity (context, cr, x, y, width, height);
+ } else {
+ fp_gtk_render_background (context, cr, x, y, width, height);
+ if (shadow_type != GTK_SHADOW_NONE) {
+ fp_gtk_render_frame(context, cr, x, y, width, height);
+ }
+ }
+
+ fp_gtk_style_context_restore (context);
+ /*
+ * Reset the text direction to the default value so that we don't
+ * accidentally affect other operations and widgets.
+ */
+ gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);
+}
+
+static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ GtkPositionType gap_side, gint gap_x, gint gap_width)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+ fp_gtk_style_context_set_state(context, flags);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+ fp_gtk_render_background(context, cr, x, y, width, height);
+
+ if (shadow_type != GTK_SHADOW_NONE) {
+ fp_gtk_render_frame_gap(context, cr, x, y, width, height, gap_side,
+ (gdouble)gap_x, (gdouble)gap_x + gap_width);
+ }
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_check(WidgetType widget_type, gint synth_state,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = get_gtk_state_flags(synth_state);
+ if (gtk3_version_3_14 && (synth_state & SELECTED)) {
+ flags = GTK_STATE_FLAG_CHECKED;
+ }
+ fp_gtk_style_context_set_state(context, flags);
+
+ fp_gtk_style_context_add_class (context, "check");
+
+ fp_gtk_render_check (context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+
+static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type,
+ const gchar *detail, gint x, gint y, gint width, gint height,
+ GtkExpanderStyle expander_style)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+ fp_gtk_style_context_set_state(context, flags);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+
+ fp_gtk_render_expander (context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_extension(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, GtkPositionType gap_side)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = GTK_STATE_FLAG_NORMAL;
+
+ if (state_type == 0) {
+ flags = GTK_STATE_FLAG_ACTIVE;
+ }
+
+ fp_gtk_style_context_set_state(context, flags);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+ switch(gap_side) {
+ case GTK_POS_LEFT:
+ fp_gtk_style_context_add_class(context, "right");
+ break;
+ case GTK_POS_RIGHT:
+ fp_gtk_style_context_add_class(context, "left");
+ break;
+ case GTK_POS_TOP:
+ fp_gtk_style_context_add_class(context, "bottom");
+ break;
+ case GTK_POS_BOTTOM:
+ fp_gtk_style_context_add_class(context, "top");
+ break;
+ default:
+ break;
+ }
+
+ fp_gtk_render_extension(context, cr, x, y, width, height, gap_side);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, gboolean has_focus)
+{
+ if (state_type == GTK_STATE_PRELIGHT &&
+ (widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) {
+ return;
+ }
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+
+ if (has_focus) {
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ }
+
+ fp_gtk_style_context_set_state (context, flags);
+
+ if (widget_type == COMBO_BOX_TEXT_FIELD) {
+ width += height /2;
+ }
+
+ fp_gtk_render_background (context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type,
+ const char *detail, gint x, gint y, gint width, gint height)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ fp_gtk_style_context_save (context);
+
+ transform_detail_string(detail, context);
+ fp_gtk_render_focus (context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+
+}
+
+static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, GtkOrientation orientation)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+ fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ fp_gtk_style_context_add_class (context, "handlebox_bin");
+ }
+
+ fp_gtk_render_handle(context, cr, x, y, width, height);
+ fp_gtk_render_background(context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+
+ fp_gtk_render_line(context, cr, x, y, x + width, y);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_vline(WidgetType widget_type, GtkStateType state_type,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+
+ fp_gtk_render_line(context, cr, x, y, x, y + height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_option(WidgetType widget_type, gint synth_state,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = get_gtk_state_flags(synth_state);
+ if (gtk3_version_3_14 && (synth_state & SELECTED)) {
+ flags = GTK_STATE_FLAG_CHECKED;
+ }
+ fp_gtk_style_context_set_state(context, flags);
+
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
+
+ fp_gtk_render_option(context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ gint synth_state, GtkTextDirection dir)
+{
+ if (shadow_type == GTK_SHADOW_NONE) {
+ return;
+ }
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ /*
+ * Some engines (e.g. clearlooks) will paint the shadow of certain
+ * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the
+ * the text direction.
+ */
+ gtk3_set_direction(gtk3_widget, dir);
+
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ fp_gtk_style_context_save (context);
+
+ if (detail) {
+ transform_detail_string(detail, context);
+ }
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+
+ if (synth_state & MOUSE_OVER) {
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ }
+
+ if (synth_state & FOCUSED) {
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ }
+
+ fp_gtk_style_context_set_state (context, flags);
+
+ if (widget_type == COMBO_BOX_TEXT_FIELD) {
+ width += height / 2;
+ }
+ fp_gtk_render_frame(context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+
+ /*
+ * Reset the text direction to the default value so that we don't
+ * accidentally affect other operations and widgets.
+ */
+ gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);
+}
+
+static void gtk3_paint_slider(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, GtkOrientation orientation,
+ gboolean has_focus)
+{
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+ fp_gtk_style_context_save (context);
+
+ if (detail) {
+ transform_detail_string(detail, context);
+ }
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+
+ if (state_type == GTK_STATE_ACTIVE) {
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ }
+
+ if (has_focus) {
+ flags |= GTK_STATE_FLAG_FOCUSED;
+ }
+
+ fp_gtk_style_context_set_state (context, flags);
+
+ (*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_background(WidgetType widget_type,
+ GtkStateType state_type, gint x, gint y, gint width, gint height) {
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ fp_gtk_style_context_save (context);
+
+ GtkStateFlags flags = get_gtk_flags(state_type);
+
+ fp_gtk_style_context_set_state (context, flags);
+
+ fp_gtk_render_background (context, cr, x, y, width, height);
+
+ fp_gtk_style_context_restore (context);
+}
+
+static GdkPixbuf *gtk3_get_stock_icon(gint widget_type, const gchar *stock_id,
+ GtkIconSize size, GtkTextDirection direction, const char *detail)
+{
+ int sz;
+
+ switch(size) {
+ case GTK_ICON_SIZE_MENU:
+ sz = 16;
+ break;
+ case GTK_ICON_SIZE_SMALL_TOOLBAR:
+ sz = 18;
+ break;
+ case GTK_ICON_SIZE_LARGE_TOOLBAR:
+ sz = 24;
+ break;
+ case GTK_ICON_SIZE_BUTTON:
+ sz = 20;
+ break;
+ case GTK_ICON_SIZE_DND:
+ sz = 32;
+ break;
+ case GTK_ICON_SIZE_DIALOG:
+ sz = 48;
+ break;
+ default:
+ sz = 0;
+ break;
+ }
+
+ init_containers();
+ gtk3_widget = gtk3_get_widget((widget_type < 0) ? IMAGE : widget_type);
+ (*fp_gtk_widget_set_direction)(gtk3_widget, direction);
+ GtkIconTheme *icon_theme = fp_gtk_icon_theme_get_default();
+ GdkPixbuf *result = fp_gtk_icon_theme_load_icon(icon_theme, stock_id, sz,
+ GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+ return result;
+}
+
+static jboolean gtk3_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,
+ jmethodID icon_upcall_method, jobject this) {
+ if (!pixbuf) {
+ return JNI_FALSE;
+ }
+ guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+ if (pixbuf_data) {
+ int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+ int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
+ int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
+ int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
+ int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+ gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
+
+ jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
+ JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+ (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
+ (jbyte *)pixbuf_data);
+ (*fp_g_object_unref)(pixbuf);
+
+ /* Call the callback method to create the image on the Java side. */
+ (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
+ width, height, row_stride, bps, channels, alpha);
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+static jboolean gtk3_get_file_icon_data(JNIEnv *env, const char *filename,
+ GError **error, jmethodID icon_upcall_method, jobject this) {
+ GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);
+ return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
+static jboolean gtk3_get_icon_data(JNIEnv *env, gint widget_type,
+ const gchar *stock_id, GtkIconSize size,
+ GtkTextDirection direction, const char *detail,
+ jmethodID icon_upcall_method, jobject this) {
+ GdkPixbuf* pixbuf = gtk3_get_stock_icon(widget_type, stock_id, size,
+ direction, detail);
+ return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
+/*************************************************/
+static gint gtk3_get_xthickness(JNIEnv *env, WidgetType widget_type)
+{
+ init_containers();
+
+ gtk3_widget = gtk3_get_widget(widget_type);
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ if (context) {
+ GtkBorder padding;
+ fp_gtk_style_context_get_padding(context, 0, &padding);
+ return padding.left + 1;
+ }
+ return 0;
+}
+
+static gint gtk3_get_ythickness(JNIEnv *env, WidgetType widget_type)
+{
+ init_containers();
+
+ gtk3_widget = gtk3_get_widget(widget_type);
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ if (context) {
+ GtkBorder padding;
+ fp_gtk_style_context_get_padding(context, 0, &padding);
+ return padding.top + 1;
+ }
+ return 0;
+}
+
+/*************************************************/
+static guint8 recode_color(gdouble channel)
+{
+ guint16 result = (guint16)(channel * 65535);
+ if (result < 0) {
+ result = 0;
+ } else if (result > 65535) {
+ result = 65535;
+ }
+ return (guint8)( result >> 8);
+}
+
+static GtkStateFlags gtk3_get_state_flags(GtkStateType state_type) {
+ switch (state_type)
+ {
+ case GTK_STATE_NORMAL:
+ return GTK_STATE_FLAG_NORMAL;
+ case GTK_STATE_ACTIVE:
+ return GTK_STATE_FLAG_ACTIVE;
+ case GTK_STATE_PRELIGHT:
+ return GTK_STATE_FLAG_PRELIGHT;
+ case GTK_STATE_SELECTED:
+ return GTK_STATE_FLAG_SELECTED;
+ case GTK_STATE_INSENSITIVE:
+ return GTK_STATE_FLAG_INSENSITIVE;
+ case GTK_STATE_INCONSISTENT:
+ return GTK_STATE_FLAG_INCONSISTENT;
+ case GTK_STATE_FOCUSED:
+ return GTK_STATE_FLAG_FOCUSED;
+ }
+ return 0;
+}
+
+
+static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) {
+ gdouble min;
+ gdouble max;
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble h, l, s;
+ gdouble delta;
+
+ red = *r;
+ green = *g;
+ blue = *b;
+
+ if (red > green)
+ {
+ if (red > blue)
+ max = red;
+ else
+ max = blue;
+
+ if (green < blue)
+ min = green;
+ else
+ min = blue;
+ }
+ else
+ {
+ if (green > blue)
+ max = green;
+ else
+ max = blue;
+
+ if (red < blue)
+ min = red;
+ else
+ min = blue;
+ }
+
+ l = (max + min) / 2;
+ s = 0;
+ h = 0;
+
+ if (max != min)
+ {
+ if (l <= 0.5)
+ s = (max - min) / (max + min);
+ else
+ s = (max - min) / (2 - max - min);
+
+ delta = max -min;
+ if (red == max)
+ h = (green - blue) / delta;
+ else if (green == max)
+ h = 2 + (blue - red) / delta;
+ else if (blue == max)
+ h = 4 + (red - green) / delta;
+
+ h *= 60;
+ if (h < 0.0)
+ h += 360;
+ }
+
+ *r = h;
+ *g = l;
+ *b = s;
+}
+
+static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s)
+{
+ gdouble hue;
+ gdouble lightness;
+ gdouble saturation;
+ gdouble m1, m2;
+ gdouble r, g, b;
+
+ lightness = *l;
+ saturation = *s;
+
+ if (lightness <= 0.5)
+ m2 = lightness * (1 + saturation);
+ else
+ m2 = lightness + saturation - lightness * saturation;
+ m1 = 2 * lightness - m2;
+
+ if (saturation == 0)
+ {
+ *h = lightness;
+ *l = lightness;
+ *s = lightness;
+ }
+ else
+ {
+ hue = *h + 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ r = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ r = m2;
+ else if (hue < 240)
+ r = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ r = m1;
+
+ hue = *h;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ g = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ g = m2;
+ else if (hue < 240)
+ g = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ g = m1;
+
+ hue = *h - 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ b = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ b = m2;
+ else if (hue < 240)
+ b = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ b = m1;
+
+ *h = r;
+ *l = g;
+ *s = b;
+ }
+}
+
+
+
+static void gtk3_style_shade (const GdkRGBA *a, GdkRGBA *b, gdouble k) {
+ gdouble red = a->red;
+ gdouble green = a->green;
+ gdouble blue = a->blue;
+
+ rgb_to_hls (&red, &green, &blue);
+
+ green *= k;
+ if (green > 1.0)
+ green = 1.0;
+ else if (green < 0.0)
+ green = 0.0;
+
+ blue *= k;
+ if (blue > 1.0)
+ blue = 1.0;
+ else if (blue < 0.0)
+ blue = 0.0;
+
+ hls_to_rgb (&red, &green, &blue);
+
+ b->red = red;
+ b->green = green;
+ b->blue = blue;
+}
+
+static GdkRGBA gtk3_get_color_for_flags(GtkStyleContext* context,
+ GtkStateFlags flags, ColorType color_type) {
+ GdkRGBA c, color;
+
+ switch (color_type)
+ {
+ case FOREGROUND:
+ case TEXT_FOREGROUND:
+ fp_gtk_style_context_get_color(context, flags, &color);
+ break;
+ case BACKGROUND:
+ case TEXT_BACKGROUND:
+ fp_gtk_style_context_get_background_color(context, flags, &color);
+ break;
+ case LIGHT:
+ c = gtk3_get_color_for_flags(context, flags, BACKGROUND);
+ gtk3_style_shade(&c, &color, LIGHTNESS_MULT);
+ break;
+ case DARK:
+ c = gtk3_get_color_for_flags(context, flags, BACKGROUND);
+ gtk3_style_shade (&c, &color, DARKNESS_MULT);
+ break;
+ case MID:
+ {
+ GdkRGBA c1 = gtk3_get_color_for_flags(context, flags, LIGHT);
+ GdkRGBA c2 = gtk3_get_color_for_flags(context, flags, DARK);
+ color.red = (c1.red + c2.red) / 2;
+ color.green = (c1.green + c2.green) / 2;
+ color.blue = (c1.blue + c2.blue) / 2;
+ }
+ break;
+ case FOCUS:
+ case BLACK:
+ color.red = 0;
+ color.green = 0;
+ color.blue = 0;
+ break;
+ case WHITE:
+ color.red = 1;
+ color.green = 1;
+ color.blue = 1;
+ break;
+ }
+ return color;
+}
+
+static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type,
+ GtkStateType state_type, ColorType color_type)
+{
+
+ gint result = 0;
+ GdkRGBA color;
+
+ GtkStateFlags flags = gtk3_get_state_flags(state_type);
+
+ init_containers();
+
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget);
+
+ if (widget_type == TOOL_TIP) {
+ fp_gtk_style_context_add_class(context, "tooltip");
+ }
+ if (widget_type == CHECK_BOX_MENU_ITEM
+ || widget_type == RADIO_BUTTON_MENU_ITEM) {
+ flags &= GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_SELECTED
+ | GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED;
+ }
+
+ color = gtk3_get_color_for_flags(context, flags, color_type);
+
+ if (recode_color(color.alpha) == 0) {
+ color = gtk3_get_color_for_flags(
+ fp_gtk_widget_get_style_context(gtk3_get_widget(INTERNAL_FRAME)),
+ 0, BACKGROUND);
+ }
+
+ result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 |
+ recode_color(color.green) << 8 | recode_color(color.blue);
+
+ return result;
+}
+
+/*************************************************/
+static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
+static jobject create_Integer(JNIEnv *env, jint int_value);
+static jobject create_Long(JNIEnv *env, jlong long_value);
+static jobject create_Float(JNIEnv *env, jfloat float_value);
+static jobject create_Double(JNIEnv *env, jdouble double_value);
+static jobject create_Character(JNIEnv *env, jchar char_value);
+static jobject create_Insets(JNIEnv *env, GtkBorder *border);
+
+static jobject gtk3_get_class_value(JNIEnv *env, WidgetType widget_type,
+ const char* key)
+{
+ init_containers();
+
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ GValue value = { 0, { { 0 } } };
+
+ GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(
+ ((GTypeInstance*)gtk3_widget)->g_class, key);
+ if ( param )
+ {
+ (*fp_g_value_init)( &value, param->value_type );
+ (*fp_gtk_widget_style_get_property)(gtk3_widget, key, &value);
+
+ if ((*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))
+ {
+ gboolean val = (*fp_g_value_get_boolean)(&value);
+ return create_Boolean(env, (jboolean)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))
+ {
+ gchar val = (*fp_g_value_get_char)(&value);
+ return create_Character(env, (jchar)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR ))
+ {
+ guchar val = (*fp_g_value_get_uchar)(&value);
+ return create_Character(env, (jchar)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT ))
+ {
+ gint val = (*fp_g_value_get_int)(&value);
+ return create_Integer(env, (jint)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT ))
+ {
+ guint val = (*fp_g_value_get_uint)(&value);
+ return create_Integer(env, (jint)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_LONG ))
+ {
+ glong val = (*fp_g_value_get_long)(&value);
+ return create_Long(env, (jlong)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG ))
+ {
+ gulong val = (*fp_g_value_get_ulong)(&value);
+ return create_Long(env, (jlong)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 ))
+ {
+ gint64 val = (*fp_g_value_get_int64)(&value);
+ return create_Long(env, (jlong)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 ))
+ {
+ guint64 val = (*fp_g_value_get_uint64)(&value);
+ return create_Long(env, (jlong)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT ))
+ {
+ gfloat val = (*fp_g_value_get_float)(&value);
+ return create_Float(env, (jfloat)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE ))
+ {
+ gdouble val = (*fp_g_value_get_double)(&value);
+ return create_Double(env, (jdouble)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM ))
+ {
+ gint val = (*fp_g_value_get_enum)(&value);
+ return create_Integer(env, (jint)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS ))
+ {
+ guint val = (*fp_g_value_get_flags)(&value);
+ return create_Integer(env, (jint)val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_STRING ))
+ {
+ const gchar* val = (*fp_g_value_get_string)(&value);
+
+ /* We suppose that all values come in C locale and
+ * utf-8 representation of a string is the same as
+ * the string itself. If this isn't so we should
+ * use g_convert.
+ */
+ return (*env)->NewStringUTF(env, val);
+ }
+ else if ((*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER ))
+ {
+ GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value);
+ return border ? create_Insets(env, border) : NULL;
+ }
+
+ /* TODO: Other types are not supported yet.*/
+/* else if((*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))
+ {
+ GParamSpec* val = (*fp_g_value_get_param)(&value);
+ printf( "Param: %p\n", val );
+ }
+ else if((*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))
+ {
+ gpointer* val = (*fp_g_value_get_boxed)(&value);
+ printf( "Boxed: %p\n", val );
+ }
+ else if((*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))
+ {
+ gpointer* val = (*fp_g_value_get_pointer)(&value);
+ printf( "Pointer: %p\n", val );
+ }
+ else if((*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))
+ {
+ GObject* val = (GObject*)(*fp_g_value_get_object)(&value);
+ printf( "Object: %p\n", val );
+ }*/
+ }
+
+ return NULL;
+}
+
+static void gtk3_set_range_value(WidgetType widget_type, jdouble value,
+ jdouble min, jdouble max, jdouble visible)
+{
+ GtkAdjustment *adj;
+
+ gtk3_widget = gtk3_get_widget(widget_type);
+
+ adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk3_widget);
+
+ fp_gtk_adjustment_set_value(adj, value);
+ fp_gtk_adjustment_set_lower(adj, min);
+ fp_gtk_adjustment_set_upper(adj, max);
+ fp_gtk_adjustment_set_page_size(adj, visible);
+}
+
+/*************************************************/
+static jobject create_Object(JNIEnv *env, jmethodID *cid,
+ const char* class_name,
+ const char* signature,
+ jvalue* value)
+{
+ jclass class;
+ jobject result;
+
+ class = (*env)->FindClass(env, class_name);
+ if (class == NULL)
+ return NULL; /* can't find/load the class, exception thrown */
+
+ if (*cid == NULL)
+ {
+ *cid = (*env)->GetMethodID(env, class, "<init>", signature);
+ if (*cid == NULL)
+ {
+ (*env)->DeleteLocalRef(env, class);
+ return NULL; /* can't find/get the method, exception thrown */
+ }
+ }
+
+ result = (*env)->NewObjectA(env, class, *cid, value);
+
+ (*env)->DeleteLocalRef(env, class);
+ return result;
+}
+
+jobject create_Boolean(JNIEnv *env, jboolean boolean_value)
+{
+ static jmethodID cid = NULL;
+ jvalue value;
+
+ value.z = boolean_value;
+
+ return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value);
+}
+
+jobject create_Integer(JNIEnv *env, jint int_value)
+{
+ static jmethodID cid = NULL;
+ jvalue value;
+
+ value.i = int_value;
+
+ return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value);
+}
+
+jobject create_Long(JNIEnv *env, jlong long_value)
+{
+ static jmethodID cid = NULL;
+ jvalue value;
+
+ value.j = long_value;
+
+ return create_Object(env, &cid, "java/lang/Long", "(J)V", &value);
+}
+
+jobject create_Float(JNIEnv *env, jfloat float_value)
+{
+ static jmethodID cid = NULL;
+ jvalue value;
+
+ value.f = float_value;
+
+ return create_Object(env, &cid, "java/lang/Float", "(F)V", &value);
+}
+
+jobject create_Double(JNIEnv *env, jdouble double_value)
+{
+ static jmethodID cid = NULL;
+ jvalue value;
+
+ value.d = double_value;
+
+ return create_Object(env, &cid, "java/lang/Double", "(D)V", &value);
+}
+
+jobject create_Character(JNIEnv *env, jchar char_value)
+{
+ static jmethodID cid = NULL;
+ jvalue value;
+
+ value.c = char_value;
+
+ return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);
+}
+
+
+jobject create_Insets(JNIEnv *env, GtkBorder *border)
+{
+ static jmethodID cid = NULL;
+ jvalue values[4];
+
+ values[0].i = border->top;
+ values[1].i = border->left;
+ values[2].i = border->bottom;
+ values[3].i = border->right;
+
+ return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);
+}
+
+/*********************************************/
+static jstring gtk3_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
+{
+ init_containers();
+
+ gtk3_widget = gtk3_get_widget(widget_type);
+ jstring result = NULL;
+ GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+ if (context)
+ {
+ PangoFontDescription* fd = fp_gtk_style_context_get_font(context, 0);
+ gchar* val = (*fp_pango_font_description_to_string)(fd);
+ result = (*env)->NewStringUTF(env, val);
+ (*fp_g_free)( val );
+ }
+
+ return result;
+}
+
+/***********************************************/
+static jobject get_string_property(JNIEnv *env, GtkSettings* settings,
+ const gchar* key) {
+ jobject result = NULL;
+ gchar* strval = NULL;
+
+ (*fp_g_object_get)(settings, key, &strval, NULL);
+ result = (*env)->NewStringUTF(env, strval);
+ (*fp_g_free)(strval);
+
+ return result;
+}
+
+static jobject get_integer_property(JNIEnv *env, GtkSettings* settings,
+ const gchar* key) {
+ gint intval = 0;
+ (*fp_g_object_get)(settings, key, &intval, NULL);
+ return create_Integer(env, intval);
+}
+
+static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings,
+ const gchar* key) {
+ gint intval = 0;
+ (*fp_g_object_get)(settings, key, &intval, NULL);
+ return create_Boolean(env, intval);
+}
+
+static jobject gtk3_get_setting(JNIEnv *env, Setting property)
+{
+ GtkSettings* settings = (*fp_gtk_settings_get_default)();
+
+ switch (property)
+ {
+ case GTK_FONT_NAME:
+ return get_string_property(env, settings, "gtk-font-name");
+ case GTK_ICON_SIZES:
+ return get_string_property(env, settings, "gtk-icon-sizes");
+ case GTK_CURSOR_BLINK:
+ return get_boolean_property(env, settings, "gtk-cursor-blink");
+ case GTK_CURSOR_BLINK_TIME:
+ return get_integer_property(env, settings, "gtk-cursor-blink-time");
+ }
+
+ return NULL;
+}
+
+static void transform_detail_string (const gchar *detail,
+ GtkStyleContext *context) {
+ if (!detail)
+ return;
+
+ if (strcmp (detail, "arrow") == 0)
+ fp_gtk_style_context_add_class (context, "arrow");
+ else if (strcmp (detail, "button") == 0)
+ fp_gtk_style_context_add_class (context, "button");
+ else if (strcmp (detail, "buttondefault") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "button");
+ fp_gtk_style_context_add_class (context, "default");
+ }
+ else if (strcmp (detail, "calendar") == 0)
+ fp_gtk_style_context_add_class (context, "calendar");
+ else if (strcmp (detail, "cellcheck") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "cell");
+ fp_gtk_style_context_add_class (context, "check");
+ }
+ else if (strcmp (detail, "cellradio") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "cell");
+ fp_gtk_style_context_add_class (context, "radio");
+ }
+ else if (strcmp (detail, "checkbutton") == 0)
+ fp_gtk_style_context_add_class (context, "check");
+ else if (strcmp (detail, "check") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "check");
+ fp_gtk_style_context_add_class (context, "menu");
+ }
+ else if (strcmp (detail, "radiobutton") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "radio");
+ }
+ else if (strcmp (detail, "option") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "radio");
+ fp_gtk_style_context_add_class (context, "menu");
+ }
+ else if (strcmp (detail, "entry") == 0 ||
+ strcmp (detail, "entry_bg") == 0)
+ fp_gtk_style_context_add_class (context, "entry");
+ else if (strcmp (detail, "expander") == 0)
+ fp_gtk_style_context_add_class (context, "expander");
+ else if (strcmp (detail, "tooltip") == 0)
+ fp_gtk_style_context_add_class (context, "tooltip");
+ else if (strcmp (detail, "frame") == 0)
+ fp_gtk_style_context_add_class (context, "frame");
+ else if (strcmp (detail, "scrolled_window") == 0)
+ fp_gtk_style_context_add_class (context, "scrolled-window");
+ else if (strcmp (detail, "viewport") == 0 ||
+ strcmp (detail, "viewportbin") == 0)
+ fp_gtk_style_context_add_class (context, "viewport");
+ else if (strncmp (detail, "trough", 6) == 0)
+ fp_gtk_style_context_add_class (context, "trough");
+ else if (strcmp (detail, "spinbutton") == 0)
+ fp_gtk_style_context_add_class (context, "spinbutton");
+ else if (strcmp (detail, "spinbutton_up") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "spinbutton");
+ fp_gtk_style_context_add_class (context, "button");
+ fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+ }
+ else if (strcmp (detail, "spinbutton_down") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "spinbutton");
+ fp_gtk_style_context_add_class (context, "button");
+ fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+ }
+ else if ((detail[0] == 'h' || detail[0] == 'v') &&
+ strncmp (&detail[1], "scrollbar_", 9) == 0)
+ {
+ fp_gtk_style_context_add_class (context, "button");
+ fp_gtk_style_context_add_class (context, "scrollbar");
+ }
+ else if (strcmp (detail, "slider") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "slider");
+ fp_gtk_style_context_add_class (context, "scrollbar");
+ }
+ else if (strcmp (detail, "vscale") == 0 ||
+ strcmp (detail, "hscale") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "slider");
+ fp_gtk_style_context_add_class (context, "scale");
+ }
+ else if (strcmp (detail, "menuitem") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "menuitem");
+ fp_gtk_style_context_add_class (context, "menu");
+ }
+ else if (strcmp (detail, "menu") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "popup");
+ fp_gtk_style_context_add_class (context, "menu");
+ }
+ else if (strcmp (detail, "accellabel") == 0)
+ fp_gtk_style_context_add_class (context, "accelerator");
+ else if (strcmp (detail, "menubar") == 0)
+ fp_gtk_style_context_add_class (context, "menubar");
+ else if (strcmp (detail, "base") == 0)
+ fp_gtk_style_context_add_class (context, "background");
+ else if (strcmp (detail, "bar") == 0 ||
+ strcmp (detail, "progressbar") == 0)
+ fp_gtk_style_context_add_class (context, "progressbar");
+ else if (strcmp (detail, "toolbar") == 0)
+ fp_gtk_style_context_add_class (context, "toolbar");
+ else if (strcmp (detail, "handlebox_bin") == 0)
+ fp_gtk_style_context_add_class (context, "dock");
+ else if (strcmp (detail, "notebook") == 0)
+ fp_gtk_style_context_add_class (context, "notebook");
+ else if (strcmp (detail, "tab") == 0)
+ {
+ fp_gtk_style_context_add_class (context, "notebook");
+ fp_gtk_style_context_add_region (context, "tab", 0);
+ } else if (strcmp (detail, "paned") == 0) {
+ fp_gtk_style_context_add_class (context, "pane-separator");
+ }
+ else if (fp_g_str_has_prefix (detail, "cell"))
+ {
+ GtkRegionFlags row, col;
+ gboolean ruled = FALSE;
+ gchar** tokens;
+ guint i;
+
+ tokens = fp_g_strsplit (detail, "_", -1);
+ row = col = 0;
+ i = 0;
+
+ while (tokens[i])
+ {
+ if (strcmp (tokens[i], "even") == 0)
+ row |= GTK_REGION_EVEN;
+ else if (strcmp (tokens[i], "odd") == 0)
+ row |= GTK_REGION_ODD;
+ else if (strcmp (tokens[i], "start") == 0)
+ col |= GTK_REGION_FIRST;
+ else if (strcmp (tokens[i], "end") == 0)
+ col |= GTK_REGION_LAST;
+ else if (strcmp (tokens[i], "ruled") == 0)
+ ruled = TRUE;
+ else if (strcmp (tokens[i], "sorted") == 0)
+ col |= GTK_REGION_SORTED;
+
+ i++;
+ }
+
+ if (!ruled)
+ row &= ~(GTK_REGION_EVEN | GTK_REGION_ODD);
+
+ fp_gtk_style_context_add_class (context, "cell");
+ fp_gtk_style_context_add_region (context, "row", row);
+ fp_gtk_style_context_add_region (context, "column", col);
+
+ fp_g_strfreev (tokens);
+ }
+}
+
+static gboolean gtk3_get_drawable_data(JNIEnv *env, jintArray pixelArray,
+ int x, jint y, jint width, jint height, jint jwidth, int dx, int dy,
+ jint scale) {
+ GdkPixbuf *pixbuf;
+ jint *ary;
+
+ GdkWindow *root = (*fp_gdk_get_default_root_window)();
+ pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(root, x, y, width, height);
+ if (pixbuf && scale != 1) {
+ GdkPixbuf *scaledPixbuf;
+ x /= scale;
+ y /= scale;
+ width /= scale;
+ height /= scale;
+ dx /= scale;
+ dy /= scale;
+ scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
+ GDK_INTERP_BILINEAR);
+ (*fp_g_object_unref)(pixbuf);
+ pixbuf = scaledPixbuf;
+ }
+
+ if (pixbuf) {
+ int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+ int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+ if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
+ && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
+ && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
+ && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
+ && nchan >= 3
+ ) {
+ guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+ ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
+ if (ary) {
+ jint _x, _y;
+ int index;
+ for (_y = 0; _y < height; _y++) {
+ for (_x = 0; _x < width; _x++) {
+ p = pix + _y * stride + _x * nchan;
+
+ index = (_y + dy) * jwidth + (_x + dx);
+ ary[index] = 0xff000000
+ | (p[0] << 16)
+ | (p[1] << 8)
+ | (p[2]);
+
+ }
+ }
+ (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
+ }
+ }
+ (*fp_g_object_unref)(pixbuf);
+ }
+ return JNI_FALSE;
+}
+
+static GdkWindow* gtk3_get_window(void *widget) {
+ return fp_gtk_widget_get_window((GtkWidget*)widget);
+}
+
+static void gtk3_init(GtkApi* gtk) {
+ gtk->version = GTK_3;
+
+ gtk->show_uri_load = >k3_show_uri_load;
+ gtk->unload = >k3_unload;
+ gtk->flush_event_loop = &flush_gtk_event_loop;
+ gtk->gtk_check_version = fp_gtk_check_version;
+ gtk->get_setting = >k3_get_setting;
+
+ gtk->paint_arrow = >k3_paint_arrow;
+ gtk->paint_box = >k3_paint_box;
+ gtk->paint_box_gap = >k3_paint_box_gap;
+ gtk->paint_expander = >k3_paint_expander;
+ gtk->paint_extension = >k3_paint_extension;
+ gtk->paint_flat_box = >k3_paint_flat_box;
+ gtk->paint_focus = >k3_paint_focus;
+ gtk->paint_handle = >k3_paint_handle;
+ gtk->paint_hline = >k3_paint_hline;
+ gtk->paint_vline = >k3_paint_vline;
+ gtk->paint_option = >k3_paint_option;
+ gtk->paint_shadow = >k3_paint_shadow;
+ gtk->paint_slider = >k3_paint_slider;
+ gtk->paint_background = >k3_paint_background;
+ gtk->paint_check = >k3_paint_check;
+ gtk->set_range_value = >k3_set_range_value;
+
+ gtk->init_painting = >k3_init_painting;
+ gtk->copy_image = >k3_copy_image;
+
+ gtk->get_xthickness = >k3_get_xthickness;
+ gtk->get_ythickness = >k3_get_ythickness;
+ gtk->get_color_for_state = >k3_get_color_for_state;
+ gtk->get_class_value = >k3_get_class_value;
+
+ gtk->get_pango_font_name = >k3_get_pango_font_name;
+ gtk->get_icon_data = >k3_get_icon_data;
+ gtk->get_file_icon_data = >k3_get_file_icon_data;
+ gtk->gdk_threads_enter = fp_gdk_threads_enter;
+ gtk->gdk_threads_leave = fp_gdk_threads_leave;
+ gtk->gtk_show_uri = fp_gtk_show_uri;
+ gtk->get_drawable_data = >k3_get_drawable_data;
+ gtk->g_free = fp_g_free;
+
+ gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;
+ gtk->gtk_widget_hide = fp_gtk_widget_hide;
+ gtk->gtk_main_quit = fp_gtk_main_quit;
+ gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;
+ gtk->gtk_file_chooser_set_current_folder =
+ fp_gtk_file_chooser_set_current_folder;
+ gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;
+ gtk->gtk_file_chooser_set_current_name =
+ fp_gtk_file_chooser_set_current_name;
+ gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;
+ gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;
+ gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;
+ gtk->gtk_file_filter_new = fp_gtk_file_filter_new;
+ gtk->gtk_file_chooser_set_do_overwrite_confirmation =
+ fp_gtk_file_chooser_set_do_overwrite_confirmation;
+ gtk->gtk_file_chooser_set_select_multiple =
+ fp_gtk_file_chooser_set_select_multiple;
+ gtk->gtk_file_chooser_get_current_folder =
+ fp_gtk_file_chooser_get_current_folder;
+ gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;
+ gtk->gtk_g_slist_length = fp_gtk_g_slist_length;
+ gtk->g_signal_connect_data = fp_g_signal_connect_data;
+ gtk->gtk_widget_show = fp_gtk_widget_show;
+ gtk->gtk_main = fp_gtk_main;
+ gtk->gtk_main_level = fp_gtk_main_level;
+ gtk->g_path_get_dirname = fp_g_path_get_dirname;
+ gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;
+ gtk->gtk_widget_destroy = fp_gtk_widget_destroy;
+ gtk->gtk_window_present = fp_gtk_window_present;
+ gtk->gtk_window_move = fp_gtk_window_move;
+ gtk->gtk_window_resize = fp_gtk_window_resize;
+ gtk->get_window = >k3_get_window;
+
+ gtk->g_object_unref = fp_g_object_unref;
+ gtk->g_list_append = fp_g_list_append;
+ gtk->g_list_free = fp_g_list_free;
+ gtk->g_list_free_full = fp_g_list_free_full;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,577 @@
+/*
+ * 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
+ * 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.
+ */
+#ifndef _GTK3_INTERFACE_H
+#define _GTK3_INTERFACE_H
+
+#include <stdlib.h>
+#include <jni.h>
+#include <X11/X.h>
+#include "gtk_interface.h"
+
+#define LIGHTNESS_MULT 1.3
+#define DARKNESS_MULT 0.7
+
+#define G_PI 3.1415926535897932384626433832795028841971693993751
+
+typedef enum
+{
+ GTK_STATE_FLAG_NORMAL = 0,
+ GTK_STATE_FLAG_ACTIVE = 1 << 0,
+ GTK_STATE_FLAG_PRELIGHT = 1 << 1,
+ GTK_STATE_FLAG_SELECTED = 1 << 2,
+ GTK_STATE_FLAG_INSENSITIVE = 1 << 3,
+ GTK_STATE_FLAG_INCONSISTENT = 1 << 4,
+ GTK_STATE_FLAG_FOCUSED = 1 << 5,
+ GTK_STATE_FLAG_BACKDROP = 1 << 6,
+ GTK_STATE_FLAG_DIR_LTR = 1 << 7,
+ GTK_STATE_FLAG_DIR_RTL = 1 << 8,
+ GTK_STATE_FLAG_LINK = 1 << 9,
+ GTK_STATE_FLAG_VISITED = 1 << 10,
+ GTK_STATE_FLAG_CHECKED = 1 << 11
+} GtkStateFlags;
+
+typedef enum {
+ GTK_JUNCTION_NONE = 0,
+ GTK_JUNCTION_CORNER_TOPLEFT = 1 << 0,
+ GTK_JUNCTION_CORNER_TOPRIGHT = 1 << 1,
+ GTK_JUNCTION_CORNER_BOTTOMLEFT = 1 << 2,
+ GTK_JUNCTION_CORNER_BOTTOMRIGHT = 1 << 3,
+ GTK_JUNCTION_TOP =
+ (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_TOPRIGHT),
+ GTK_JUNCTION_BOTTOM =
+ (GTK_JUNCTION_CORNER_BOTTOMLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT),
+ GTK_JUNCTION_LEFT =
+ (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT),
+ GTK_JUNCTION_RIGHT =
+ (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT)
+} GtkJunctionSides;
+
+typedef enum {
+ GTK_REGION_EVEN = 1 << 0,
+ GTK_REGION_ODD = 1 << 1,
+ GTK_REGION_FIRST = 1 << 2,
+ GTK_REGION_LAST = 1 << 3,
+ GTK_REGION_ONLY = 1 << 4,
+ GTK_REGION_SORTED = 1 << 5
+} GtkRegionFlags;
+
+typedef enum
+{
+ GTK_WINDOW_TOPLEVEL,
+ GTK_WINDOW_POPUP
+} GtkWindowType;
+
+typedef enum
+{
+ G_PARAM_READABLE = 1 << 0,
+ G_PARAM_WRITABLE = 1 << 1,
+ G_PARAM_CONSTRUCT = 1 << 2,
+ G_PARAM_CONSTRUCT_ONLY = 1 << 3,
+ G_PARAM_LAX_VALIDATION = 1 << 4,
+ G_PARAM_STATIC_NAME = 1 << 5
+} GParamFlags;
+
+typedef enum
+{
+ GTK_ICON_LOOKUP_NO_SVG = 1 << 0,
+ GTK_ICON_LOOKUP_FORCE_SVG = 1 << 1,
+ GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2,
+ GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3,
+ GTK_ICON_LOOKUP_FORCE_SIZE = 1 << 4
+} GtkIconLookupFlags;
+
+typedef enum
+{
+ GTK_UPDATE_CONTINUOUS,
+ GTK_UPDATE_DISCONTINUOUS,
+ GTK_UPDATE_DELAYED
+} GtkUpdateType;
+
+typedef enum
+{
+ GTK_PROGRESS_CONTINUOUS,
+ GTK_PROGRESS_DISCRETE
+} GtkProgressBarStyle;
+
+typedef enum
+{
+ GTK_PROGRESS_LEFT_TO_RIGHT,
+ GTK_PROGRESS_RIGHT_TO_LEFT,
+ GTK_PROGRESS_BOTTOM_TO_TOP,
+ GTK_PROGRESS_TOP_TO_BOTTOM
+} GtkProgressBarOrientation;
+
+typedef enum {
+ CAIRO_FORMAT_INVALID = -1,
+ CAIRO_FORMAT_ARGB32 = 0,
+ CAIRO_FORMAT_RGB24 = 1,
+ CAIRO_FORMAT_A8 = 2,
+ CAIRO_FORMAT_A1 = 3,
+ CAIRO_FORMAT_RGB16_565 = 4
+} cairo_format_t;
+
+/* We define all structure pointers to be void* */
+typedef void GdkPixbuf;
+typedef void GMainContext;
+typedef void GVfs;
+
+typedef void GdkColormap;
+typedef void GdkDrawable;
+typedef void GdkGC;
+typedef void GdkPixmap;
+typedef void GtkStyleContext;
+typedef void GtkFixed;
+typedef void GtkMenuItem;
+typedef void GtkMenuShell;
+typedef void GtkWidgetClass;
+typedef void PangoFontDescription;
+typedef void GtkSettings;
+typedef void GtkStyleProvider;
+typedef void cairo_pattern_t;
+typedef void cairo_t;
+typedef void cairo_surface_t;
+typedef void GtkScrolledWindow;
+typedef void GtkIconTheme;
+typedef void GtkWidget;
+typedef void GtkMisc;
+typedef void GtkContainer;
+typedef void GtkBin;
+typedef void GtkAdjustment;
+typedef void GtkRange;
+typedef void GtkProgressBar;
+typedef void GtkProgress;
+
+/* Some real structures */
+typedef struct
+{
+ guint32 pixel;
+ guint16 red;
+ guint16 green;
+ guint16 blue;
+} GdkColor;
+
+typedef struct
+{
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble alpha;
+} GdkRGBA;
+
+typedef struct {
+ gint fd;
+ gushort events;
+ gushort revents;
+} GPollFD;
+
+typedef struct {
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+} GdkRectangle;
+
+typedef struct {
+ int x, y;
+ int width, height;
+} GtkAllocation;
+
+typedef struct {
+ gint width;
+ gint height;
+} GtkRequisition;
+
+typedef struct {
+ GtkWidgetClass *g_class;
+} GTypeInstance;
+
+typedef struct {
+ gint16 left;
+ gint16 right;
+ gint16 top;
+ gint16 bottom;
+} GtkBorder;
+
+typedef struct
+{
+ GType g_type;
+ union {
+ gint v_int;
+ guint v_uint;
+ glong v_long;
+ gulong v_ulong;
+ gint64 v_int64;
+ guint64 v_uint64;
+ gfloat v_float;
+ gdouble v_double;
+ gpointer v_pointer;
+ } data[2];
+} GValue;
+
+typedef struct {
+ GTypeInstance g_type_instance;
+ const gchar *name;
+ GParamFlags flags;
+ GType value_type;
+ GType owner_type;
+} GParamSpec;
+
+
+static gchar* (*fp_glib_check_version)(guint required_major,
+ guint required_minor, guint required_micro);
+
+/**
+ * Returns :
+ * NULL if the GTK+ library is compatible with the given version, or a string
+ * describing the version mismatch.
+ */
+static gchar* (*fp_gtk_check_version)(guint required_major, guint
+ required_minor, guint required_micro);
+
+static void (*fp_g_free)(gpointer mem);
+static void (*fp_g_object_unref)(gpointer object);
+static GdkWindow *(*fp_gdk_get_default_root_window) (void);
+
+static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf);
+static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
+static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
+static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename,
+ GError **error);
+static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf);
+
+static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkWindow *window,
+ int src_x, int src_y, int width, int height);
+static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
+ int dest_width, int dest_heigh, GdkInterpType interp_type);
+
+
+static void (*fp_gtk_widget_destroy)(void *widget);
+static void (*fp_gtk_window_present)(GtkWindow *window);
+static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
+static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height);
+
+/**
+ * Function Pointers for GtkFileChooser
+ */
+static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
+static void (*fp_gtk_widget_hide)(void *widget);
+static void (*fp_gtk_main_quit)(void);
+static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title,
+ GtkWindow *parent, GtkFileChooserAction action,
+ const gchar *first_button_text, ...);
+static gboolean (*fp_gtk_file_chooser_set_current_folder)
+ (GtkFileChooser *chooser, const gchar *filename);
+static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
+ const char *filename);
+static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
+ const gchar *name);
+static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter,
+ GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data,
+ GDestroyNotify notify);
+static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
+ GtkFileFilter *filter);
+static GType (*fp_gtk_file_chooser_get_type)(void);
+static GtkFileFilter* (*fp_gtk_file_filter_new)(void);
+static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)(
+ GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
+static void (*fp_gtk_file_chooser_set_select_multiple)(
+ GtkFileChooser *chooser, gboolean select_multiple);
+static gchar* (*fp_gtk_file_chooser_get_current_folder)
+ (GtkFileChooser *chooser);
+static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
+static guint (*fp_gtk_g_slist_length)(GSList *list);
+static gulong (*fp_g_signal_connect_data)(gpointer instance,
+ const gchar *detailed_signal, GCallback c_handler, gpointer data,
+ GClosureNotify destroy_data, GConnectFlags connect_flags);
+static void (*fp_gtk_widget_show)(void *widget);
+static void (*fp_gtk_main)(void);
+static guint (*fp_gtk_main_level)(void);
+static gchar* (*fp_g_path_get_dirname) (const gchar *file_name);
+static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable);
+
+static GList* (*fp_g_list_append) (GList *list, gpointer data);
+static void (*fp_g_list_free) (GList *list);
+static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
+
+static void (*fp_gdk_threads_enter)(void);
+static void (*fp_gdk_threads_leave)(void);
+
+static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
+ guint32 timestamp, GError **error);
+
+// Implementation functions prototypes
+static void gtk3_init(GtkApi* gtk);
+static GValue* (*fp_g_value_init)(GValue *value, GType g_type);
+static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type);
+static gboolean (*fp_g_value_get_boolean)(const GValue *value);
+static gchar (*fp_g_value_get_char)(const GValue *value);
+static guchar (*fp_g_value_get_uchar)(const GValue *value);
+static gint (*fp_g_value_get_int)(const GValue *value);
+static guint (*fp_g_value_get_uint)(const GValue *value);
+static glong (*fp_g_value_get_long)(const GValue *value);
+static gulong (*fp_g_value_get_ulong)(const GValue *value);
+static gint64 (*fp_g_value_get_int64)(const GValue *value);
+static guint64 (*fp_g_value_get_uint64)(const GValue *value);
+static gfloat (*fp_g_value_get_float)(const GValue *value);
+static gdouble (*fp_g_value_get_double)(const GValue *value);
+static const gchar* (*fp_g_value_get_string)(const GValue *value);
+static gint (*fp_g_value_get_enum)(const GValue *value);
+static guint (*fp_g_value_get_flags)(const GValue *value);
+static GParamSpec* (*fp_g_value_get_param)(const GValue *value);
+static gpointer* (*fp_g_value_get_boxed)(const GValue *value);
+static gpointer* (*fp_g_value_get_pointer)(const GValue *value);
+static void (*fp_g_object_get)(gpointer object,
+ const gchar* fpn, ...);
+static void (*fp_g_object_set)(gpointer object,
+ const gchar *first_property_name,
+ ...);
+
+static gboolean (*fp_g_main_context_iteration)(GMainContext *context);
+static gboolean (*fp_g_str_has_prefix)(const gchar *str, const gchar *prefix);
+static gchar** (*fp_g_strsplit)(const gchar *string, const gchar *delimiter,
+ gint max_tokens);
+static void (*fp_g_strfreev)(gchar **str_array);
+
+
+static cairo_surface_t* (*fp_cairo_image_surface_create)(cairo_format_t format,
+ int width, int height);
+static void (*fp_cairo_surface_destroy)(cairo_surface_t *surface);
+static cairo_t* (*fp_cairo_create)(cairo_surface_t *target);
+static void (*fp_cairo_destroy)(cairo_t *cr);
+static void (*fp_cairo_fill)(cairo_t *cr);
+static void (*fp_cairo_surface_flush)(cairo_surface_t *surface);
+static void (*fp_cairo_rectangle)(cairo_t *cr, double x, double y, double width,
+ double height);
+static void (*fp_cairo_set_source_rgb)(cairo_t *cr, double red, double green,
+ double blue);
+static void (*fp_cairo_set_source_rgba)(cairo_t *cr, double red, double green,
+ double blue, double alpha);
+static void (*fp_cairo_paint)(cairo_t *cr);
+static void (*fp_cairo_clip)(cairo_t *cr);
+static unsigned char* (*fp_cairo_image_surface_get_data)(
+ cairo_surface_t *surface);
+static int (*fp_cairo_image_surface_get_stride) (cairo_surface_t *surface);
+static GdkPixbuf* (*fp_gdk_pixbuf_get_from_surface)(cairo_surface_t *surface,
+ gint src_x, gint src_y, gint width, gint height);
+static GtkStateType (*fp_gtk_widget_get_state)(GtkWidget *widget);
+static void (*fp_gtk_widget_set_state)(GtkWidget *widget, GtkStateType state);
+static gboolean (*fp_gtk_widget_is_focus)(GtkWidget *widget);
+static void (*fp_gtk_widget_set_allocation)(GtkWidget *widget,
+ const GtkAllocation *allocation);
+static GtkWidget* (*fp_gtk_widget_get_parent)(GtkWidget *widget);
+static GtkStyleContext* (*fp_gtk_widget_get_style_context)(GtkWidget *widget);
+static void (*fp_gtk_style_context_get_color)(GtkStyleContext *context,
+ GtkStateFlags state, GdkRGBA *color);
+static void (*fp_gtk_style_context_get_background_color)
+ (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color);
+static void (*fp_gtk_style_context_get)(GtkStyleContext *context,
+ GtkStateFlags state, ...);
+static GtkStateFlags (*fp_gtk_widget_get_state_flags)(GtkWidget* widget);
+static void (*fp_gtk_style_context_set_state)(GtkStyleContext* style,
+ GtkStateFlags flags);
+static void (*fp_gtk_style_context_add_class)(GtkStyleContext *context,
+ const gchar *class_name);
+static void (*fp_gtk_style_context_save)(GtkStyleContext *context);
+static void (*fp_gtk_style_context_restore)(GtkStyleContext *context);
+static void (*fp_gtk_render_check)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_option)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_extension)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height,
+ GtkPositionType gap_side);
+static void (*fp_gtk_render_expander)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_frame_gap)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height,
+ GtkPositionType gap_side, gdouble xy0_gap,
+ gdouble xy1_gap);
+static void (*fp_gtk_render_line)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x0, gdouble y0, gdouble x1, gdouble y1);
+static GdkPixbuf* (*fp_gtk_widget_render_icon_pixbuf)(GtkWidget *widget,
+ const gchar *stock_id, GtkIconSize size);
+static cairo_surface_t* (*fp_gdk_window_create_similar_image_surface)(
+ GdkWindow *window, cairo_format_t format, int width,
+ int height, int scale);
+static cairo_surface_t* (*fp_gdk_window_create_similar_surface)(
+ GdkWindow *window, cairo_format_t format,
+ int width, int height);
+static GdkWindow* (*fp_gtk_widget_get_window)(GtkWidget *widget);
+static GtkSettings *(*fp_gtk_settings_get_for_screen)(GdkScreen *screen);
+static GdkScreen *(*fp_gtk_widget_get_screen)(GtkWidget *widget);
+static GtkStyleProvider* (*fp_gtk_css_provider_get_named)(const gchar *name,
+ const gchar *variant);
+static void (*fp_gtk_style_context_add_provider)(GtkStyleContext *context,
+ GtkStyleProvider *provider, guint priority);
+static void (*fp_gtk_render_frame)(GtkStyleContext *context,cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_focus)(GtkStyleContext *context,cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_handle)(GtkStyleContext *context,cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_style_context_get_property)(GtkStyleContext *context,
+ const gchar *property, GtkStateFlags state, GValue *value);
+static void (*fp_gtk_render_activity)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_background)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height);
+static gboolean (*fp_gtk_style_context_has_class)(GtkStyleContext *context,
+ const gchar *class_name);
+static void transform_detail_string (const gchar *detail,
+ GtkStyleContext *context);
+void (*fp_gtk_style_context_set_junction_sides)(GtkStyleContext *context,
+ GtkJunctionSides sides);
+void (*fp_gtk_style_context_add_region)(GtkStyleContext *context,
+ const gchar *region_name, GtkRegionFlags flags);
+void (*fp_gtk_render_arrow)(GtkStyleContext *context, cairo_t *cr,
+ gdouble angle, gdouble x, gdouble y, gdouble size);
+void (*fp_gtk_bin_set_child)(GtkBin *bin, GtkWidget *widget);
+void (*fp_gtk_scrolled_window_set_shadow_type)(
+ GtkScrolledWindow *scrolled_window, GtkShadowType type);
+static void (*fp_gtk_render_slider)(GtkStyleContext *context, cairo_t *cr,
+ gdouble x, gdouble y, gdouble width, gdouble height,
+ GtkOrientation orientation);
+static void (*fp_gtk_style_context_get_padding)(GtkStyleContext *self,
+ GtkStateFlags state, GtkBorder* padding);
+static void (*fp_gtk_range_set_inverted)(GtkRange *range, gboolean setting);
+static PangoFontDescription* (*fp_gtk_style_context_get_font)(
+ GtkStyleContext *context, GtkStateFlags state);
+static int (*fp_gtk_widget_get_allocated_width)(GtkWidget *widget);
+static int (*fp_gtk_widget_get_allocated_height)(GtkWidget *widget);
+static GtkIconTheme* (*fp_gtk_icon_theme_get_default)(void);
+static GdkPixbuf* (*fp_gtk_icon_theme_load_icon)(GtkIconTheme *icon_theme,
+ const gchar *icon_name, gint size,
+ GtkIconLookupFlags flags, GError **error);
+static void (*fp_gtk_adjustment_set_lower)(GtkAdjustment *adjustment,
+ gdouble lower);
+static void (*fp_gtk_adjustment_set_page_increment)(GtkAdjustment *adjustment,
+ gdouble page_increment);
+static void (*fp_gtk_adjustment_set_page_size)(GtkAdjustment *adjustment,
+ gdouble page_size);
+static void (*fp_gtk_adjustment_set_step_increment)(GtkAdjustment *adjustment,
+ gdouble step_increment);
+static void (*fp_gtk_adjustment_set_upper)(GtkAdjustment *adjustment,
+ gdouble upper);
+static void (*fp_gtk_adjustment_set_value)(GtkAdjustment *adjustment,
+ gdouble value);
+static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*);
+static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32);
+static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean,
+ gint, gint, gint, gint);
+static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace,
+ gboolean has_alpha, int bits_per_sample, int width, int height);
+static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable,
+ gint* width, gint* height);
+static gboolean (*fp_gtk_init_check)(int* argc, char** argv);
+
+/* Widget creation */
+static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type,
+ GtkShadowType shadow_type);
+static GtkWidget* (*fp_gtk_button_new)();
+static GtkWidget* (*fp_gtk_check_button_new)();
+static GtkWidget* (*fp_gtk_check_menu_item_new)();
+static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title);
+static GtkWidget* (*fp_gtk_combo_box_new)();
+static GtkWidget* (*fp_gtk_combo_box_entry_new)();
+static GtkWidget* (*fp_gtk_entry_new)();
+static GtkWidget* (*fp_gtk_fixed_new)();
+static GtkWidget* (*fp_gtk_handle_box_new)();
+static GtkWidget* (*fp_gtk_hpaned_new)();
+static GtkWidget* (*fp_gtk_vpaned_new)();
+static GtkWidget* (*fp_gtk_scale_new)(GtkOrientation orientation,
+ GtkAdjustment* adjustment);
+static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment);
+static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment);
+static GtkWidget* (*fp_gtk_hseparator_new)();
+static GtkWidget* (*fp_gtk_vseparator_new)();
+static GtkWidget* (*fp_gtk_image_new)();
+static GtkWidget* (*fp_gtk_label_new)(const gchar* str);
+static GtkWidget* (*fp_gtk_menu_new)();
+static GtkWidget* (*fp_gtk_menu_bar_new)();
+static GtkWidget* (*fp_gtk_menu_item_new)();
+static GtkWidget* (*fp_gtk_notebook_new)();
+static GtkWidget* (*fp_gtk_progress_bar_new)();
+static GtkWidget* (*fp_gtk_progress_bar_set_orientation)(
+ GtkProgressBar *pbar,
+ GtkProgressBarOrientation orientation);
+static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group);
+static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group);
+static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+static GtkWidget* (*fp_gtk_separator_menu_item_new)();
+static GtkWidget* (*fp_gtk_separator_tool_item_new)();
+static GtkWidget* (*fp_gtk_text_view_new)();
+static GtkWidget* (*fp_gtk_toggle_button_new)();
+static GtkWidget* (*fp_gtk_toolbar_new)();
+static GtkWidget* (*fp_gtk_tree_view_new)();
+static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type);
+static GtkWidget* (*fp_gtk_dialog_new)();
+static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment,
+ gdouble climb_rate, guint digits);
+static GtkWidget* (*fp_gtk_frame_new)(const gchar *label);
+
+/* Other widget operations */
+static GtkAdjustment* (*fp_gtk_adjustment_new)(gdouble value,
+ gdouble lower, gdouble upper, gdouble step_increment,
+ gdouble page_increment, gdouble page_size);
+static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget);
+static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell,
+ GtkWidget *child);
+static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item,
+ GtkWidget *submenu);
+static void (*fp_gtk_widget_realize)(GtkWidget *widget);
+static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget,
+ const gchar *stock_id, GtkIconSize size, const gchar *detail);
+static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name);
+static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent);
+static void (*fp_gtk_widget_set_direction)(GtkWidget *widget,
+ GtkTextDirection direction);
+static void (*fp_gtk_widget_style_get)(GtkWidget *widget,
+ const gchar *first_property_name, ...);
+static void (*fp_gtk_widget_class_install_style_property)(
+ GtkWidgetClass* class, GParamSpec *pspec);
+static GParamSpec* (*fp_gtk_widget_class_find_style_property)(
+ GtkWidgetClass* class, const gchar* property_name);
+static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,
+ const gchar* property_name, GValue* value);
+static char* (*fp_pango_font_description_to_string)(
+ const PangoFontDescription* fd);
+static GtkSettings* (*fp_gtk_settings_get_default)();
+static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);
+static GType (*fp_gtk_border_get_type)();
+static void (*fp_gtk_arrow_set)(GtkWidget* arrow,
+ GtkArrowType arrow_type,
+ GtkShadowType shadow_type);
+static void (*fp_gtk_widget_size_request)(GtkWidget *widget,
+ GtkRequisition *requisition);
+static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);
+
+#endif /* !_GTK3_INTERFACE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,158 @@
+/*
+ * 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
+ * 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.
+ */
+#include <dlfcn.h>
+#include <stdlib.h>
+#include "jvm_md.h"
+#include "gtk_interface.h"
+
+GtkApi* gtk2_load(JNIEnv *env, const char* lib_name);
+GtkApi* gtk3_load(JNIEnv *env, const char* lib_name);
+
+gboolean gtk2_check(const char* lib_name, int flags);
+gboolean gtk3_check(const char* lib_name, int flags);
+
+GtkApi *gtk;
+
+typedef struct {
+ GtkVersion version;
+ const char* name;
+ const char* vname;
+ GtkApi* (*load)(JNIEnv *env, const char* lib_name);
+ gboolean (*check)(const char* lib_name, int flags);
+} GtkLib;
+
+static GtkLib libs[] = {
+ {
+ GTK_2,
+ JNI_LIB_NAME("gtk-x11-2.0"),
+ VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"),
+ >k2_load,
+ >k2_check
+ },
+ {
+ GTK_3,
+ JNI_LIB_NAME("gtk-3"),
+ VERSIONED_JNI_LIB_NAME("gtk-3", "0"),
+ >k3_load,
+ >k3_check
+ },
+ {
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ }
+};
+
+static GtkLib* get_loaded() {
+ GtkLib* lib = libs;
+ while(!gtk && lib->version) {
+ if (lib->check(lib->vname, RTLD_NOLOAD)) {
+ return lib;
+ }
+ if (lib->check(lib->name, RTLD_NOLOAD)) {
+ return lib;
+ }
+ lib++;
+ }
+ return NULL;
+}
+
+gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose) {
+ if (gtk == NULL) {
+ GtkLib* lib = get_loaded();
+ if (lib) {
+ if (version != GTK_ANY && lib->version != version) {
+ if (verbose) {
+ fprintf(stderr, "WARNING: Cannot load GTK%d library: \
+ GTK%d has already been loaded\n", version, lib->version);
+ }
+ return FALSE;
+ }
+ if (verbose) {
+ fprintf(stderr, "Looking for GTK%d library...\n", version);
+ }
+ gtk = lib->load(env, lib->vname);
+ if (!gtk) {
+ gtk = lib->load(env, lib->name);
+ }
+ } else {
+ lib = libs;
+ while (!gtk && lib->version) {
+ if (version == GTK_ANY || lib->version == version) {
+ if (verbose) {
+ fprintf(stderr, "Looking for GTK%d library...\n",
+ lib->version);
+ }
+ gtk = lib->load(env, lib->vname);
+ if (!gtk) {
+ gtk = lib->load(env, lib->name);
+ }
+ if (verbose && !gtk) {
+ fprintf(stderr, "Not found.\n");
+ }
+ }
+ lib++;
+ }
+ lib--;
+ }
+ if (verbose) {
+ if (gtk) {
+ fprintf(stderr, "GTK%d library loaded.\n", lib->version);
+ } else {
+ fprintf(stderr, "Failed to load GTK library.\n");
+ }
+ }
+ }
+ return gtk != NULL;
+}
+
+static gboolean check_version(GtkVersion version, int flags) {
+ GtkLib* lib = libs;
+ while (lib->version) {
+ if (version == GTK_ANY || lib->version == version) {
+ if (lib->check(lib->vname, flags)) {
+ return TRUE;
+ }
+ if (lib->check(lib->name, flags)) {
+ return TRUE;
+ }
+ }
+ lib++;
+ }
+ return FALSE;
+}
+
+gboolean gtk_check_version(GtkVersion version) {
+ if (gtk) {
+ return TRUE;
+ }
+ if (check_version(version, RTLD_NOLOAD)) {
+ return TRUE;
+ }
+ return check_version(version, RTLD_LAZY | RTLD_LOCAL);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,560 @@
+/*
+ * 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
+ * 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.
+ */
+#ifndef _GTK_INTERFACE_H
+#define _GTK_INTERFACE_H
+
+#include <X11/X.h>
+#include <jni.h>
+
+#ifndef FALSE
+#define FALSE (0)
+#define TRUE (!FALSE)
+#endif
+
+#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
+#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) \
+ (_G_TYPE_CIC ((instance), (g_type), c_type))
+#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ())
+#define GTK_FILE_CHOOSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser))
+#define G_CALLBACK(f) ((GCallback) (f))
+#define G_TYPE_FUNDAMENTAL_SHIFT (2)
+#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
+#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
+#define GTK_STOCK_CANCEL "gtk-cancel"
+#define GTK_STOCK_SAVE "gtk-save"
+#define GTK_STOCK_OPEN "gtk-open"
+#define GDK_CURRENT_TIME 0L
+
+#define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0)
+#define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1)
+#define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2)
+#define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3)
+#define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4)
+#define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5)
+#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6)
+#define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7)
+#define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8)
+#define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9)
+#define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10)
+#define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11)
+#define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12)
+#define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13)
+#define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14)
+#define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15)
+#define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16)
+#define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17)
+#define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18)
+#define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19)
+#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
+
+#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())
+
+#define G_TYPE_FUNDAMENTAL_SHIFT (2)
+#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define CONV_BUFFER_SIZE 128
+#define NO_SYMBOL_EXCEPTION 1
+
+/* basic types */
+typedef char gchar;
+typedef short gshort;
+typedef int gint;
+typedef long glong;
+typedef float gfloat;
+typedef double gdouble;
+typedef void* gpointer;
+typedef gint gboolean;
+typedef signed char gint8;
+typedef signed short gint16;
+typedef signed int gint32;
+typedef unsigned char guchar;
+typedef unsigned char guint8;
+typedef unsigned short gushort;
+typedef unsigned short guint16;
+typedef unsigned int guint;
+typedef unsigned int guint32;
+typedef unsigned int gsize;
+typedef unsigned long gulong;
+typedef signed long long gint64;
+typedef unsigned long long guint64;
+typedef gulong GType;
+
+typedef struct _GList GList;
+struct _GList
+{
+ gpointer data;
+ GList *next;
+ GList *prev;
+};
+
+typedef struct _GSList GSList;
+struct _GSList {
+ gpointer data;
+ GSList *next;
+};
+
+typedef enum {
+ BUTTON, /* GtkButton */
+ CHECK_BOX, /* GtkCheckButton */
+ CHECK_BOX_MENU_ITEM, /* GtkCheckMenuItem */
+ COLOR_CHOOSER, /* GtkColorSelectionDialog */
+ COMBO_BOX, /* GtkComboBox */
+ COMBO_BOX_ARROW_BUTTON, /* GtkComboBoxEntry */
+ COMBO_BOX_TEXT_FIELD, /* GtkComboBoxEntry */
+ DESKTOP_ICON, /* GtkLabel */
+ DESKTOP_PANE, /* GtkContainer */
+ EDITOR_PANE, /* GtkTextView */
+ FORMATTED_TEXT_FIELD, /* GtkEntry */
+ HANDLE_BOX, /* GtkHandleBox */
+ HPROGRESS_BAR, /* GtkProgressBar */
+ HSCROLL_BAR, /* GtkHScrollbar */
+ HSCROLL_BAR_BUTTON_LEFT, /* GtkHScrollbar */
+ HSCROLL_BAR_BUTTON_RIGHT, /* GtkHScrollbar */
+ HSCROLL_BAR_TRACK, /* GtkHScrollbar */
+ HSCROLL_BAR_THUMB, /* GtkHScrollbar */
+ HSEPARATOR, /* GtkHSeparator */
+ HSLIDER, /* GtkHScale */
+ HSLIDER_TRACK, /* GtkHScale */
+ HSLIDER_THUMB, /* GtkHScale */
+ HSPLIT_PANE_DIVIDER, /* GtkHPaned */
+ INTERNAL_FRAME, /* GtkWindow */
+ INTERNAL_FRAME_TITLE_PANE, /* GtkLabel */
+ IMAGE, /* GtkImage */
+ LABEL, /* GtkLabel */
+ LIST, /* GtkTreeView */
+ MENU, /* GtkMenu */
+ MENU_BAR, /* GtkMenuBar */
+ MENU_ITEM, /* GtkMenuItem */
+ MENU_ITEM_ACCELERATOR, /* GtkLabel */
+ OPTION_PANE, /* GtkMessageDialog */
+ PANEL, /* GtkContainer */
+ PASSWORD_FIELD, /* GtkEntry */
+ POPUP_MENU, /* GtkMenu */
+ POPUP_MENU_SEPARATOR, /* GtkSeparatorMenuItem */
+ RADIO_BUTTON, /* GtkRadioButton */
+ RADIO_BUTTON_MENU_ITEM, /* GtkRadioMenuItem */
+ ROOT_PANE, /* GtkContainer */
+ SCROLL_PANE, /* GtkScrolledWindow */
+ SPINNER, /* GtkSpinButton */
+ SPINNER_ARROW_BUTTON, /* GtkSpinButton */
+ SPINNER_TEXT_FIELD, /* GtkSpinButton */
+ SPLIT_PANE, /* GtkPaned */
+ TABBED_PANE, /* GtkNotebook */
+ TABBED_PANE_TAB_AREA, /* GtkNotebook */
+ TABBED_PANE_CONTENT, /* GtkNotebook */
+ TABBED_PANE_TAB, /* GtkNotebook */
+ TABLE, /* GtkTreeView */
+ TABLE_HEADER, /* GtkButton */
+ TEXT_AREA, /* GtkTextView */
+ TEXT_FIELD, /* GtkEntry */
+ TEXT_PANE, /* GtkTextView */
+ TITLED_BORDER, /* GtkFrame */
+ TOGGLE_BUTTON, /* GtkToggleButton */
+ TOOL_BAR, /* GtkToolbar */
+ TOOL_BAR_DRAG_WINDOW, /* GtkToolbar */
+ TOOL_BAR_SEPARATOR, /* GtkSeparatorToolItem */
+ TOOL_TIP, /* GtkWindow */
+ TREE, /* GtkTreeView */
+ TREE_CELL, /* GtkTreeView */
+ VIEWPORT, /* GtkViewport */
+ VPROGRESS_BAR, /* GtkProgressBar */
+ VSCROLL_BAR, /* GtkVScrollbar */
+ VSCROLL_BAR_BUTTON_UP, /* GtkVScrollbar */
+ VSCROLL_BAR_BUTTON_DOWN, /* GtkVScrollbar */
+ VSCROLL_BAR_TRACK, /* GtkVScrollbar */
+ VSCROLL_BAR_THUMB, /* GtkVScrollbar */
+ VSEPARATOR, /* GtkVSeparator */
+ VSLIDER, /* GtkVScale */
+ VSLIDER_TRACK, /* GtkVScale */
+ VSLIDER_THUMB, /* GtkVScale */
+ VSPLIT_PANE_DIVIDER, /* GtkVPaned */
+ WIDGET_TYPE_SIZE
+} WidgetType;
+
+typedef enum
+{
+ _GTK_ARROW_TYPE,
+ _GTK_BUTTON_TYPE,
+ _GTK_CHECK_BUTTON_TYPE,
+ _GTK_CHECK_MENU_ITEM_TYPE,
+ _GTK_COLOR_SELECTION_DIALOG_TYPE,
+ _GTK_COMBO_BOX_TYPE,
+ _GTK_COMBO_BOX_ARROW_BUTTON_TYPE,
+ _GTK_COMBO_BOX_TEXT_FIELD_TYPE,
+ _GTK_CONTAINER_TYPE,
+ _GTK_ENTRY_TYPE,
+ _GTK_FRAME_TYPE,
+ _GTK_HANDLE_BOX_TYPE,
+ _GTK_HPANED_TYPE,
+ _GTK_HPROGRESS_BAR_TYPE,
+ _GTK_HSCALE_TYPE,
+ _GTK_HSCROLLBAR_TYPE,
+ _GTK_HSEPARATOR_TYPE,
+ _GTK_IMAGE_TYPE,
+ _GTK_MENU_TYPE,
+ _GTK_MENU_BAR_TYPE,
+ _GTK_MENU_ITEM_TYPE,
+ _GTK_NOTEBOOK_TYPE,
+ _GTK_LABEL_TYPE,
+ _GTK_RADIO_BUTTON_TYPE,
+ _GTK_RADIO_MENU_ITEM_TYPE,
+ _GTK_SCROLLED_WINDOW_TYPE,
+ _GTK_SEPARATOR_MENU_ITEM_TYPE,
+ _GTK_SEPARATOR_TOOL_ITEM_TYPE,
+ _GTK_SPIN_BUTTON_TYPE,
+ _GTK_TEXT_VIEW_TYPE,
+ _GTK_TOGGLE_BUTTON_TYPE,
+ _GTK_TOOLBAR_TYPE,
+ _GTK_TOOLTIP_TYPE,
+ _GTK_TREE_VIEW_TYPE,
+ _GTK_VIEWPORT_TYPE,
+ _GTK_VPANED_TYPE,
+ _GTK_VPROGRESS_BAR_TYPE,
+ _GTK_VSCALE_TYPE,
+ _GTK_VSCROLLBAR_TYPE,
+ _GTK_VSEPARATOR_TYPE,
+ _GTK_WINDOW_TYPE,
+ _GTK_DIALOG_TYPE,
+ _GTK_WIDGET_TYPE_SIZE
+} GtkWidgetType;
+
+typedef enum
+{
+ GTK_STATE_NORMAL,
+ GTK_STATE_ACTIVE,
+ GTK_STATE_PRELIGHT,
+ GTK_STATE_SELECTED,
+ GTK_STATE_INSENSITIVE,
+ GTK_STATE_INCONSISTENT,
+ GTK_STATE_FOCUSED
+} GtkStateType;
+
+typedef enum
+{
+ GTK_SHADOW_NONE,
+ GTK_SHADOW_IN,
+ GTK_SHADOW_OUT,
+ GTK_SHADOW_ETCHED_IN,
+ GTK_SHADOW_ETCHED_OUT
+} GtkShadowType;
+
+typedef enum
+{
+ GTK_EXPANDER_COLLAPSED,
+ GTK_EXPANDER_SEMI_COLLAPSED,
+ GTK_EXPANDER_SEMI_EXPANDED,
+ GTK_EXPANDER_EXPANDED
+} GtkExpanderStyle;
+
+typedef enum
+{
+ GTK_ICON_SIZE_INVALID,
+ GTK_ICON_SIZE_MENU,
+ GTK_ICON_SIZE_SMALL_TOOLBAR,
+ GTK_ICON_SIZE_LARGE_TOOLBAR,
+ GTK_ICON_SIZE_BUTTON,
+ GTK_ICON_SIZE_DND,
+ GTK_ICON_SIZE_DIALOG
+} GtkIconSize;
+
+typedef enum
+{
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_ORIENTATION_VERTICAL
+} GtkOrientation;
+
+typedef enum
+{
+ FOREGROUND,
+ BACKGROUND,
+ TEXT_FOREGROUND,
+ TEXT_BACKGROUND,
+ FOCUS,
+ LIGHT,
+ DARK,
+ MID,
+ BLACK,
+ WHITE
+} ColorType;
+
+typedef enum
+{
+ GTK_FONT_NAME,
+ GTK_ICON_SIZES,
+ GTK_CURSOR_BLINK,
+ GTK_CURSOR_BLINK_TIME
+} Setting;
+
+typedef enum
+{
+ GTK_ARROW_UP,
+ GTK_ARROW_DOWN,
+ GTK_ARROW_LEFT,
+ GTK_ARROW_RIGHT,
+ GTK_ARROW_NONE
+} GtkArrowType;
+
+typedef enum
+{
+ GTK_TEXT_DIR_NONE,
+ GTK_TEXT_DIR_LTR,
+ GTK_TEXT_DIR_RTL
+} GtkTextDirection;
+
+typedef enum
+{
+ GTK_POS_LEFT,
+ GTK_POS_RIGHT,
+ GTK_POS_TOP,
+ GTK_POS_BOTTOM
+} GtkPositionType;
+
+/* SynthConstants */
+static const gint ENABLED = 1 << 0;
+static const gint MOUSE_OVER = 1 << 1;
+static const gint PRESSED = 1 << 2;
+static const gint DISABLED = 1 << 3;
+static const gint FOCUSED = 1 << 8;
+static const gint SELECTED = 1 << 9;
+static const gint DEFAULT = 1 << 10;
+
+typedef enum
+{
+ GTK_ANY,
+ GTK_1,
+ GTK_2,
+ GTK_3
+} GtkVersion;
+
+//------------------------------
+
+
+
+typedef enum {
+ GTK_RESPONSE_NONE = -1,
+ GTK_RESPONSE_REJECT = -2,
+ GTK_RESPONSE_ACCEPT = -3,
+ GTK_RESPONSE_DELETE_EVENT = -4,
+ GTK_RESPONSE_OK = -5,
+ GTK_RESPONSE_CANCEL = -6,
+ GTK_RESPONSE_CLOSE = -7,
+ GTK_RESPONSE_YES = -8,
+ GTK_RESPONSE_NO = -9,
+ GTK_RESPONSE_APPLY = -10,
+ GTK_RESPONSE_HELP = -11
+} GtkResponseType;
+
+typedef enum {
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+} GtkFileChooserAction;
+
+typedef enum {
+ GTK_FILE_FILTER_FILENAME = 1 << 0,
+ GTK_FILE_FILTER_URI = 1 << 1,
+ GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
+ GTK_FILE_FILTER_MIME_TYPE = 1 << 3
+} GtkFileFilterFlags;
+
+typedef enum {
+ GDK_COLORSPACE_RGB
+} GdkColorspace;
+
+typedef enum {
+ GDK_INTERP_NEAREST,
+ GDK_INTERP_TILES,
+ GDK_INTERP_BILINEAR,
+ GDK_INTERP_HYPER
+} GdkInterpType;
+
+typedef enum {
+ G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1
+} GConnectFlags;
+//------------------------------
+
+
+typedef void GError;
+typedef void GdkScreen;
+typedef void GtkWindow;
+typedef void GdkWindow;
+typedef void GClosure;
+typedef void GtkFileChooser;
+typedef void GtkFileFilter;
+typedef struct {
+ GtkFileFilterFlags contains;
+ const gchar *filename;
+ const gchar *uri;
+ const gchar *display_name;
+ const gchar *mime_type;
+} GtkFileFilterInfo;
+typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info,
+ gpointer data);
+typedef void (*GClosureNotify)(gpointer data, GClosure *closure);
+typedef void (*GDestroyNotify)(gpointer data);
+typedef void (*GCallback)(void);
+
+
+typedef struct GtkApi {
+ int version;
+ gboolean (*show_uri_load)(JNIEnv *env);
+ gboolean (*unload)();
+ void (*flush_event_loop)();
+ gchar* (*gtk_check_version)(guint required_major, guint required_minor,
+ guint required_micro);
+ jobject (*get_setting)(JNIEnv *env, Setting property);
+
+ void (*paint_arrow)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ GtkArrowType arrow_type, gboolean fill);
+ void (*paint_box)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ gint synth_state, GtkTextDirection dir);
+ void (*paint_box_gap)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ GtkPositionType gap_side, gint gap_x, gint gap_width);
+ void (*paint_expander)(WidgetType widget_type, GtkStateType state_type,
+ const gchar *detail, gint x, gint y, gint width, gint height,
+ GtkExpanderStyle expander_style);
+ void (*paint_extension)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, GtkPositionType gap_side);
+ void (*paint_flat_box)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, gboolean has_focus);
+ void (*paint_focus)(WidgetType widget_type, GtkStateType state_type,
+ const char *detail, gint x, gint y, gint width, gint height);
+ void (*paint_handle)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, GtkOrientation orientation);
+ void (*paint_hline)(WidgetType widget_type, GtkStateType state_type,
+ const gchar *detail, gint x, gint y, gint width, gint height);
+ void (*paint_vline)(WidgetType widget_type, GtkStateType state_type,
+ const gchar *detail, gint x, gint y, gint width, gint height);
+ void (*paint_option)(WidgetType widget_type, gint synth_state,
+ const gchar *detail, gint x, gint y, gint width, gint height);
+ void (*paint_shadow)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height,
+ gint synth_state, GtkTextDirection dir);
+ void (*paint_slider)(WidgetType widget_type, GtkStateType state_type,
+ GtkShadowType shadow_type, const gchar *detail,
+ gint x, gint y, gint width, gint height, GtkOrientation orientation,
+ gboolean has_focus);
+ void (*paint_background)(WidgetType widget_type, GtkStateType state_type,
+ gint x, gint y, gint width, gint height);
+ void (*paint_check)(WidgetType widget_type, gint synth_state,
+ const gchar *detail, gint x, gint y, gint width, gint height);
+ void (*set_range_value)(WidgetType widget_type, jdouble value,
+ jdouble min, jdouble max, jdouble visible);
+
+ void (*init_painting)(JNIEnv *env, gint w, gint h);
+ gint (*copy_image)(gint *dest, gint width, gint height);
+
+ gint (*get_xthickness)(JNIEnv *env, WidgetType widget_type);
+ gint (*get_ythickness)(JNIEnv *env, WidgetType widget_type);
+ gint (*get_color_for_state)(JNIEnv *env, WidgetType widget_type,
+ GtkStateType state_type, ColorType color_type);
+ jobject (*get_class_value)(JNIEnv *env, WidgetType widget_type,
+ const char* key);
+
+ jstring (*get_pango_font_name)(JNIEnv *env, WidgetType widget_type);
+ jboolean (*get_icon_data)(JNIEnv *env, gint widget_type,
+ const gchar *stock_id, GtkIconSize size,
+ GtkTextDirection direction, const char *detail,
+ jmethodID icon_upcall_method, jobject this);
+ jboolean (*get_file_icon_data)(JNIEnv *env, const char *filename,
+ GError **error, jmethodID icon_upcall_method, jobject this);
+ void (*gdk_threads_enter)(void);
+ void (*gdk_threads_leave)(void);
+ gboolean (*gtk_show_uri)(GdkScreen *screen, const gchar *uri,
+ guint32 timestamp, GError **error);
+ gboolean (*get_drawable_data)(JNIEnv *env, jintArray pixelArray,
+ jint x, jint y, jint width, jint height,
+ jint jwidth, int dx, int dy, jint scale);
+ void (*g_free)(gpointer mem);
+
+
+ gchar* (*gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
+ void (*gtk_widget_hide)(void* widget);
+ void (*gtk_main_quit)(void);
+ void* (*gtk_file_chooser_dialog_new)(const gchar *title,
+ GtkWindow *parent, GtkFileChooserAction action,
+ const gchar *first_button_text, ...);
+ gboolean (*gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser,
+ const gchar *filename);
+ gboolean (*gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
+ const char *filename);
+ void (*gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
+ const gchar *name);
+ void (*gtk_file_filter_add_custom)(GtkFileFilter *filter,
+ GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data,
+ GDestroyNotify notify);
+ void (*gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
+ GtkFileFilter *filter);
+ GType (*gtk_file_chooser_get_type)(void);
+ GtkFileFilter* (*gtk_file_filter_new)(void);
+ void (*gtk_file_chooser_set_do_overwrite_confirmation)(
+ GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
+ void (*gtk_file_chooser_set_select_multiple)(
+ GtkFileChooser *chooser, gboolean select_multiple);
+ gchar* (*gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
+ GSList* (*gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
+ guint (*gtk_g_slist_length)(GSList *list);
+ gulong (*g_signal_connect_data)(gpointer instance,
+ const gchar *detailed_signal, GCallback c_handler, gpointer data,
+ GClosureNotify destroy_data, GConnectFlags connect_flags);
+ void (*gtk_widget_show)(void *widget);
+ void (*gtk_main)(void);
+ guint (*gtk_main_level)(void);
+ gchar* (*g_path_get_dirname) (const gchar *file_name);
+ XID (*gdk_x11_drawable_get_xid) (void *drawable);
+ void (*gtk_widget_destroy)(void *widget);
+ void (*gtk_window_present)(void *window);
+ void (*gtk_window_move)(void *window, gint x, gint y);
+ void (*gtk_window_resize)(void *window, gint width, gint height);
+ GdkWindow *(*get_window)(void *widget);
+
+ void (*g_object_unref)(gpointer object);
+ GList* (*g_list_append) (GList *list, gpointer data);
+ void (*g_list_free) (GList *list);
+ void (*g_list_free_full) (GList *list, GDestroyNotify free_func);
+} GtkApi;
+
+gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose);
+gboolean gtk_check_version(GtkVersion version);
+
+extern GtkApi* gtk;
+
+#endif /* !_GTK_INTERFACE_H */
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,11 +28,12 @@
#include <jni_util.h>
#include <string.h>
#include <X11/X.h>
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
#include "sun_awt_X11_GtkFileDialogPeer.h"
#include "java_awt_FileDialog.h"
#include "debug_assert.h"
+typedef void GtkWidget;
static JavaVM *jvm;
/* To cache some method IDs */
@@ -90,20 +91,20 @@
{
// Callbacks from GTK signals are made within the GTK lock
// So, within a signal handler there is no need to call
- // gdk_threads_enter() / fp_gdk_threads_leave()
+ // gdk_threads_enter() / gtk->gdk_threads_leave()
if (!isSignalHandler) {
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
}
- fp_gtk_widget_hide (dialog);
- fp_gtk_widget_destroy (dialog);
+ gtk->gtk_widget_hide (dialog);
+ gtk->gtk_widget_destroy (dialog);
- fp_gtk_main_quit ();
+ gtk->gtk_main_quit ();
(*env)->SetLongField(env, jpeer, widgetFieldID, 0);
if (!isSignalHandler) {
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
}
@@ -133,16 +134,16 @@
{
GtkWidget * dialog;
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
dialog = (GtkWidget*)jlong_to_ptr(
(*env)->GetLongField(env, jpeer, widgetFieldID));
if (dialog != NULL) {
- fp_gtk_window_present((GtkWindow*)dialog);
+ gtk->gtk_window_present((GtkWindow*)dialog);
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -155,21 +156,21 @@
{
GtkWindow* dialog;
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
dialog = (GtkWindow*)jlong_to_ptr(
(*env)->GetLongField(env, jpeer, widgetFieldID));
if (dialog != NULL) {
if (x >= 0 && y >= 0) {
- fp_gtk_window_move(dialog, (gint)x, (gint)y);
+ gtk->gtk_window_move(dialog, (gint)x, (gint)y);
}
if (width > 0 && height > 0) {
- fp_gtk_window_resize(dialog, (gint)width, (gint)height);
+ gtk->gtk_window_resize(dialog, (gint)width, (gint)height);
}
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -182,18 +183,18 @@
gboolean isAllDirsSame = TRUE;
while (it) {
- gchar* dir = fp_g_path_get_dirname((gchar*) it->data);
+ gchar* dir = gtk->g_path_get_dirname((gchar*) it->data);
if (prevDir && strcmp(prevDir, dir) != 0) {
isAllDirsSame = FALSE;
- fp_g_free(dir);
+ gtk->g_free(dir);
break;
}
if (!prevDir) {
prevDir = strdup(dir);
}
- fp_g_free(dir);
+ gtk->g_free(dir);
it = it->next;
}
@@ -233,7 +234,7 @@
return NULL;
}
- array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL);
+ array = (*env)->NewObjectArray(env, gtk->gtk_g_slist_length(list), stringCls, NULL);
if (array == NULL) {
(*env)->ExceptionClear(env);
JNU_ThrowInternalError(env, "Could not instantiate array files array");
@@ -287,7 +288,7 @@
filenames = NULL;
if (responseId == GTK_RESPONSE_ACCEPT) {
- filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog));
+ filenames = gtk->gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog));
}
jfilenames = toFilenamesArray(env, filenames, &jcurrent_folder);
@@ -318,7 +319,7 @@
JNU_CHECK_EXCEPTION(env);
}
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0);
if (title == NULL) {
@@ -329,19 +330,19 @@
if (mode == java_awt_FileDialog_SAVE) {
/* Save action */
- dialog = fp_gtk_file_chooser_dialog_new(title, NULL,
+ dialog = gtk->gtk_file_chooser_dialog_new(title, NULL,
GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
}
else {
/* Default action OPEN */
- dialog = fp_gtk_file_chooser_dialog_new(title, NULL,
+ dialog = gtk->gtk_file_chooser_dialog_new(title, NULL,
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
/* Set multiple selection mode, that is allowed only in OPEN action */
if (multiple) {
- fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog),
+ gtk->gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog),
multiple);
}
}
@@ -358,7 +359,7 @@
JNU_ThrowOutOfMemoryError(env, "Could not get dir");
return;
}
- fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
+ gtk->gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
(*env)->ReleaseStringUTFChars(env, jdir, dir);
}
@@ -371,47 +372,48 @@
return;
}
if (mode == java_awt_FileDialog_SAVE) {
- fp_gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename);
+ gtk->gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename);
} else {
- fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename);
+ gtk->gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename);
}
(*env)->ReleaseStringUTFChars(env, jfile, filename);
}
/* Set the file filter */
if (jfilter != NULL) {
- filter = fp_gtk_file_filter_new();
- fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
+ filter = gtk->gtk_file_filter_new();
+ gtk->gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
filenameFilterCallback, jpeer, NULL);
- fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
+ gtk->gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
}
/* Other Properties */
- if (fp_gtk_check_version(2, 8, 0) == NULL) {
- fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(
+ if (gtk->gtk_check_version(2, 8, 0) == NULL ||
+ gtk->gtk_check_version(3, 0, 0) == NULL) {
+ gtk->gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(
dialog), TRUE);
}
/* Set the initial location */
if (x >= 0 && y >= 0) {
- fp_gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y);
+ gtk->gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y);
// NOTE: it doesn't set the initial size for the file chooser
// as it seems like the file chooser overrides the size internally
}
- fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
- handle_response), jpeer);
+ gtk->g_signal_connect_data(dialog, "response", G_CALLBACK(
+ handle_response), jpeer, 0, 0);
(*env)->SetLongField(env, jpeer, widgetFieldID, ptr_to_jlong(dialog));
- fp_gtk_widget_show(dialog);
+ gtk->gtk_widget_show(dialog);
- XID xid = fp_gdk_x11_drawable_get_xid(dialog->window);
+ XID xid = gtk->gdk_x11_drawable_get_xid(gtk->get_window(dialog));
if( (*env)->CallBooleanMethod(env, jpeer, setWindowMethodID, xid) ) {
- fp_gtk_main();
+ gtk->gtk_main();
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, 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
@@ -24,9 +24,24 @@
*/
#include <stdlib.h>
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
#include "com_sun_java_swing_plaf_gtk_GTKEngine.h"
+/* Static buffer for conversion from java.lang.String to UTF-8 */
+static char conversionBuffer[CONV_BUFFER_SIZE];
+
+const char *getStrFor(JNIEnv *env, jstring val)
+{
+ int length = (*env)->GetStringLength(env, val);
+ if (length > CONV_BUFFER_SIZE-1)
+ {
+ length = CONV_BUFFER_SIZE-1;
+ }
+
+ (*env)->GetStringUTFRegion(env, val, 0, length, conversionBuffer);
+ return conversionBuffer;
+}
+
/*
* Class: com_sun_java_swing_plaf_gtk_GTKEngine
* Method: native_paint_arrow
@@ -38,10 +53,10 @@
jint widget_type, jint state, jint shadow_type, jstring detail,
jint x, jint y, jint w, jint h, jint arrow_type)
{
- fp_gdk_threads_enter();
- gtk2_paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail),
x, y, w, h, arrow_type, TRUE);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -56,10 +71,10 @@
jint x, jint y, jint w, jint h,
jint synth_state, jint dir)
{
- fp_gdk_threads_enter();
- gtk2_paint_box(widget_type, state, shadow_type, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_box(widget_type, state, shadow_type, getStrFor(env, detail),
x, y, w, h, synth_state, dir);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -74,10 +89,10 @@
jint x, jint y, jint w, jint h,
jint gap_side, jint gap_x, jint gap_w)
{
- fp_gdk_threads_enter();
- gtk2_paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail),
x, y, w, h, gap_side, gap_x, gap_w);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -91,10 +106,10 @@
jint widget_type, jint synth_state, jstring detail,
jint x, jint y, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk2_paint_check(widget_type, synth_state, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_check(widget_type, synth_state, getStrFor(env, detail),
x, y, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -108,10 +123,10 @@
jint widget_type, jint state, jstring detail,
jint x, jint y, jint w, jint h, jint expander_style)
{
- fp_gdk_threads_enter();
- gtk2_paint_expander(widget_type, state, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_expander(widget_type, state, getStrFor(env, detail),
x, y, w, h, expander_style);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -125,10 +140,10 @@
jint widget_type, jint state, jint shadow_type, jstring detail,
jint x, jint y, jint w, jint h, jint placement)
{
- fp_gdk_threads_enter();
- gtk2_paint_extension(widget_type, state, shadow_type,
+ gtk->gdk_threads_enter();
+ gtk->paint_extension(widget_type, state, shadow_type,
getStrFor(env, detail), x, y, w, h, placement);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -142,10 +157,10 @@
jint widget_type, jint state, jint shadow_type, jstring detail,
jint x, jint y, jint w, jint h, jboolean has_focus)
{
- fp_gdk_threads_enter();
- gtk2_paint_flat_box(widget_type, state, shadow_type,
+ gtk->gdk_threads_enter();
+ gtk->paint_flat_box(widget_type, state, shadow_type,
getStrFor(env, detail), x, y, w, h, has_focus);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -159,10 +174,10 @@
jint widget_type, jint state, jstring detail,
jint x, jint y, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk2_paint_focus(widget_type, state, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_focus(widget_type, state, getStrFor(env, detail),
x, y, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -176,10 +191,10 @@
jint widget_type, jint state, jint shadow_type, jstring detail,
jint x, jint y, jint w, jint h, jint orientation)
{
- fp_gdk_threads_enter();
- gtk2_paint_handle(widget_type, state, shadow_type, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_handle(widget_type, state, shadow_type, getStrFor(env, detail),
x, y, w, h, orientation);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -193,10 +208,10 @@
jint widget_type, jint state, jstring detail,
jint x, jint y, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk2_paint_hline(widget_type, state, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_hline(widget_type, state, getStrFor(env, detail),
x, y, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -210,10 +225,10 @@
jint widget_type, jint synth_state, jstring detail,
jint x, jint y, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk2_paint_option(widget_type, synth_state, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_option(widget_type, synth_state, getStrFor(env, detail),
x, y, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -228,10 +243,10 @@
jint x, jint y, jint w, jint h,
jint synth_state, jint dir)
{
- fp_gdk_threads_enter();
- gtk2_paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail),
x, y, w, h, synth_state, dir);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -243,12 +258,12 @@
Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1slider(
JNIEnv *env, jobject this,
jint widget_type, jint state, jint shadow_type, jstring detail,
- jint x, jint y, jint w, jint h, jint orientation)
+ jint x, jint y, jint w, jint h, jint orientation, jboolean has_focus)
{
- fp_gdk_threads_enter();
- gtk2_paint_slider(widget_type, state, shadow_type, getStrFor(env, detail),
- x, y, w, h, orientation);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ gtk->paint_slider(widget_type, state, shadow_type, getStrFor(env, detail),
+ x, y, w, h, orientation, has_focus);
+ gtk->gdk_threads_leave();
}
/*
@@ -262,10 +277,10 @@
jint widget_type, jint state, jstring detail,
jint x, jint y, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk2_paint_vline(widget_type, state, getStrFor(env, detail),
+ gtk->gdk_threads_enter();
+ gtk->paint_vline(widget_type, state, getStrFor(env, detail),
x, y, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -278,9 +293,9 @@
JNIEnv *env, jobject this, jint widget_type, jint state,
jint x, jint y, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk_paint_background(widget_type, state, x, y, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ gtk->paint_background(widget_type, state, x, y, w, h);
+ gtk->gdk_threads_leave();
}
/*
@@ -292,9 +307,9 @@
Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeStartPainting(
JNIEnv *env, jobject this, jint w, jint h)
{
- fp_gdk_threads_enter();
- gtk2_init_painting(env, w, h);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ gtk->init_painting(env, w, h);
+ gtk->gdk_threads_leave();
}
/*
@@ -308,9 +323,9 @@
{
jint transparency;
gint *buffer = (gint*) (*env)->GetPrimitiveArrayCritical(env, dest, 0);
- fp_gdk_threads_enter();
- transparency = gtk2_copy_image(buffer, width, height);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ transparency = gtk->copy_image(buffer, width, height);
+ gtk->gdk_threads_leave();
(*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0);
return transparency;
}
@@ -324,7 +339,9 @@
JNIEnv *env, jobject this)
{
// Note that flush_gtk_event_loop takes care of locks (7053002)
- flush_gtk_event_loop();
+ gtk->gdk_threads_enter();
+ gtk->flush_event_loop();
+ gtk->gdk_threads_leave();
}
/*
@@ -336,9 +353,9 @@
JNIEnv *env, jobject this, jint property)
{
jobject obj;
- fp_gdk_threads_enter();
- obj = gtk2_get_setting(env, property);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ obj = gtk->get_setting(env, property);
+ gtk->gdk_threads_leave();
return obj;
}
@@ -352,7 +369,7 @@
JNIEnv *env, jobject this, jint widget_type,
jdouble value, jdouble min, jdouble max, jdouble visible)
{
- fp_gdk_threads_enter();
- gtk2_set_range_value(widget_type, value, min, max, visible);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ gtk->set_range_value(widget_type, value, min, max, visible);
+ gtk->gdk_threads_leave();
}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, 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
@@ -24,9 +24,12 @@
*/
#include <stdlib.h>
-#include "gtk2_interface.h"
+#include <stdio.h>
+#include "gtk_interface.h"
#include "com_sun_java_swing_plaf_gtk_GTKStyle.h"
+const char *getStrFor(JNIEnv *env, jstring val);
+
/*
* Class: com_sun_java_swing_plaf_gtk_GTKStyle
* Method: nativeGetXThickness
@@ -37,9 +40,9 @@
JNIEnv *env, jclass klass, jint widget_type)
{
jint ret;
- fp_gdk_threads_enter();
- ret = gtk2_get_xthickness(env, widget_type);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ ret = gtk->get_xthickness(env, widget_type);
+ gtk->gdk_threads_leave();
return ret;
}
@@ -53,9 +56,9 @@
JNIEnv *env, jclass klass, jint widget_type)
{
jint ret;
- fp_gdk_threads_enter();
- ret = gtk2_get_ythickness(env, widget_type);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ ret = gtk->get_ythickness(env, widget_type);
+ gtk->gdk_threads_leave();
return ret;
}
@@ -70,9 +73,9 @@
jint state_type, jint type_id)
{
jint ret;
- fp_gdk_threads_enter();
- ret = gtk2_get_color_for_state(env, widget_type, state_type, type_id);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ ret = gtk->get_color_for_state(env, widget_type, state_type, type_id);
+ gtk->gdk_threads_leave();
return ret;
}
@@ -86,9 +89,9 @@
JNIEnv *env, jclass klass, jint widget_type, jstring key)
{
jobject ret;
- fp_gdk_threads_enter();
- ret = gtk2_get_class_value(env, widget_type, key);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ ret = gtk->get_class_value(env, widget_type, getStrFor(env, key));
+ gtk->gdk_threads_leave();
return ret;
}
@@ -102,8 +105,8 @@
JNIEnv *env, jclass klass, jint widget_type)
{
jstring ret;
- fp_gdk_threads_enter();
- ret = gtk2_get_pango_font_name(env, widget_type);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ ret = gtk->get_pango_font_name(env, widget_type);
+ gtk->gdk_threads_leave();
return ret;
}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c Fri May 06 06:23:30 2016 -0700
@@ -354,7 +354,6 @@
static void waitForEvents(JNIEnv *, jlong);
static void awt_pipe_init();
-static void processOneEvent(XtInputMask iMask);
static Boolean performPoll(JNIEnv *, jlong);
static void wakeUp();
static void update_poll_timeout(int timeout_control);
@@ -614,7 +613,7 @@
} /* get_poll_timeout() */
/*
- * Waits for X/Xt events to appear on the pipe. Returns only when
+ * Waits for X events to appear on the pipe. Returns only when
* it is likely (but not definite) that there are events waiting to
* be processed.
*
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -24,7 +24,7 @@
*/
#include "jni_util.h"
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
#include "gnome_interface.h"
static gboolean gtk_has_been_loaded = FALSE;
@@ -36,14 +36,14 @@
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XDesktopPeer_init
- (JNIEnv *env, jclass cls)
+ (JNIEnv *env, jclass cls, jint version, jboolean verbose)
{
if (gtk_has_been_loaded || gnome_has_been_loaded) {
return JNI_TRUE;
}
- if (gtk2_load(env) && gtk2_show_uri_load(env)) {
+ if (gtk_load(env, version, verbose) && gtk->show_uri_load(env)) {
gtk_has_been_loaded = TRUE;
return JNI_TRUE;
} else if (gnome_load()) {
@@ -74,9 +74,9 @@
}
if (gtk_has_been_loaded) {
- fp_gdk_threads_enter();
- success = fp_gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL);
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ success = gtk->gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL);
+ gtk->gdk_threads_leave();
} else if (gnome_has_been_loaded) {
success = (*gnome_url_show)(url_c, NULL);
}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c Fri May 06 06:23:30 2016 -0700
@@ -109,7 +109,7 @@
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XTaskbarPeer_init
-(JNIEnv *env, jclass cls, jstring jname) {
+(JNIEnv *env, jclass cls, jstring jname, jint version, jboolean verbose) {
jclass clazz;
jTaskbarCls = (*env)->NewGlobalRef(env, cls);
@@ -121,7 +121,7 @@
CHECK_NULL_RETURN(
jMenuItemGetLabel = (*env)->GetMethodID(env, clazz, "getLabel", "()Ljava/lang/String;"), JNI_FALSE);
- if (gtk2_load(env) && unity_load()) {
+ if (gtk_load(env, version, verbose) && unity_load()) {
const gchar* name = (*env)->GetStringUTFChars(env, jname, NULL);
if (name) {
entry = fp_unity_launcher_entry_get_for_desktop_file(name);
@@ -139,9 +139,9 @@
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_runloop
(JNIEnv *env, jclass cls) {
- fp_gdk_threads_enter();
- fp_gtk_main();
- fp_gdk_threads_leave();
+ gtk->gdk_threads_enter();
+ gtk->gtk_main();
+ gtk->gdk_threads_leave();
}
/*
@@ -151,14 +151,14 @@
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setBadge
(JNIEnv *env, jobject obj, jlong value, jboolean visible) {
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
fp_unity_launcher_entry_set_count(entry, value);
fp_unity_launcher_entry_set_count_visible(entry, visible);
DbusmenuMenuitem* m;
if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
fp_unity_launcher_entry_set_quicklist(entry, m);
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -168,13 +168,13 @@
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setUrgent
(JNIEnv *env, jobject obj, jboolean urgent) {
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
fp_unity_launcher_entry_set_urgent(entry, urgent);
DbusmenuMenuitem* m;
if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
fp_unity_launcher_entry_set_quicklist(entry, m);
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
/*
@@ -184,14 +184,14 @@
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_updateProgress
(JNIEnv *env, jobject obj, jdouble value, jboolean visible) {
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
fp_unity_launcher_entry_set_progress(entry, value);
fp_unity_launcher_entry_set_progress_visible(entry, visible);
DbusmenuMenuitem* m;
if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
fp_unity_launcher_entry_set_quicklist(entry, m);
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
void deleteGlobalRef(gpointer data) {
@@ -209,7 +209,7 @@
}
elem = (*env)->NewGlobalRef(env, elem);
- globalRefs = fp_g_list_append(globalRefs, elem);
+ globalRefs = gtk->g_list_append(globalRefs, elem);
jstring jlabel = (jstring) (*env)->CallObjectMethod(env, elem, jMenuItemGetLabel);
if (!(*env)->ExceptionCheck(env) && jlabel) {
@@ -224,7 +224,8 @@
(*env)->ReleaseStringUTFChars(env, jlabel, label);
fp_dbusmenu_menuitem_child_append(menu, mi);
- fp_g_signal_connect(mi, "item_activated", G_CALLBACK(callback), elem);
+ gtk->g_signal_connect_data(mi, "item_activated",
+ G_CALLBACK(callback), elem, NULL, 0);
}
}
}
@@ -238,7 +239,7 @@
JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setNativeMenu
(JNIEnv *env, jobject obj, jobjectArray items) {
- fp_gdk_threads_enter();
+ gtk->gdk_threads_enter();
if (!menu) {
menu = fp_dbusmenu_menuitem_new();
@@ -247,14 +248,14 @@
fp_unity_launcher_entry_set_quicklist(entry, menu);
GList* list = fp_dbusmenu_menuitem_take_children(menu);
- fp_g_list_free_full(list, fp_g_object_unref);
+ gtk->g_list_free_full(list, gtk->g_object_unref);
- fp_g_list_free_full(globalRefs, deleteGlobalRef);
+ gtk->g_list_free_full(globalRefs, deleteGlobalRef);
globalRefs = NULL;
if (items) {
fill_menu(env, items);
}
- fp_gdk_threads_leave();
+ gtk->gdk_threads_leave();
}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h Fri May 06 06:23:30 2016 -0700
@@ -26,7 +26,7 @@
#ifndef AWT_TASKBAR_H
#define AWT_TASKBAR_H
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
typedef void UnityLauncherEntry;
typedef void DbusmenuMenuitem;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
#ifndef _GNOME_INTERFACE_H
#define _GNOME_INTERFACE_H
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
#include <dlfcn.h>
#include <jvm_md.h>
#include <jni.h>
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
import java.awt.peer.*;
import java.awt.image.VolatileImage;
import sun.awt.RepaintArea;
-import sun.awt.CausedFocusEvent;
import sun.awt.image.SunVolatileImage;
import sun.awt.image.ToolkitImage;
import java.awt.image.BufferedImage;
@@ -321,7 +320,7 @@
WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target))
{
WKeyboardFocusManagerPeer.requestFocusFor((Component)target,
- CausedFocusEvent.Cause.MOUSE_EVENT);
+ FocusEvent.Cause.MOUSE_EVENT);
}
break;
}
@@ -687,7 +686,7 @@
@Override
public boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
- CausedFocusEvent.Cause cause)
+ FocusEvent.Cause cause)
{
if (WKeyboardFocusManagerPeer.
processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
package sun.awt.windows;
import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
import java.awt.dnd.DropTarget;
import java.awt.peer.*;
import java.io.File;
@@ -34,7 +35,6 @@
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.util.Vector;
-import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
@@ -282,7 +282,7 @@
@Override
public boolean requestFocus
(Component lightweightChild, boolean temporary,
- boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
+ boolean focusedWindowChangeAllowed, long time, Cause cause)
{
return false;
}
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
import sun.awt.AWTAccessor;
import sun.awt.AWTAccessor.ComponentAccessor;
import sun.awt.KeyboardFocusManagerPeerImpl;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent.Cause;
final class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
static native void setNativeFocusOwner(ComponentPeer peer);
@@ -75,7 +75,7 @@
boolean temporary,
boolean focusedWindowChangeAllowed,
long time,
- CausedFocusEvent.Cause cause)
+ Cause cause)
{
// TODO: do something to eliminate this forwarding
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,11 @@
package sun.awt.windows;
import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
import java.awt.peer.DialogPeer;
import java.awt.peer.ComponentPeer;
import java.awt.dnd.DropTarget;
import java.util.Vector;
-import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
class WPrintDialogPeer extends WWindowPeer implements DialogPeer {
@@ -153,7 +153,7 @@
@Override
public boolean requestFocus
(Component lightweightChild, boolean temporary,
- boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
+ boolean focusedWindowChangeAllowed, long time, Cause cause)
{
return false;
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -300,11 +300,11 @@
return getNativeWindowSize();
}
- public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
+ public boolean requestWindowFocus(FocusEvent.Cause cause) {
if (!focusAllowedFor()) {
return false;
}
- return requestWindowFocus(cause == CausedFocusEvent.Cause.MOUSE_EVENT);
+ return requestWindowFocus(cause == FocusEvent.Cause.MOUSE_EVENT);
}
private native boolean requestWindowFocus(boolean isMouseEventCause);
--- a/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c Fri May 06 06:23:30 2016 -0700
@@ -157,6 +157,9 @@
if (hBitmap != 0) { \
DeleteObject(hBitmap); \
} \
+ if (tmpBitmap != 0) { \
+ DeleteObject(tmpBitmap); \
+ } \
if (dibImage != NULL) { \
free(dibImage); \
} \
@@ -196,6 +199,7 @@
int bmWidth, bmHeight;
int x, y;
HBITMAP hBitmap = NULL, hOrigBM;
+ HBITMAP tmpBitmap = NULL;
int gamma, orient;
HWND hWnd = NULL;
@@ -250,6 +254,12 @@
}
oldFont = SelectObject(hMemoryDC, hFont);
+ tmpBitmap = CreateCompatibleBitmap(hDesktopDC, 1, 1);
+ if (tmpBitmap == NULL) {
+ FREE_AND_RETURN;
+ }
+ hOrigBM = (HBITMAP)SelectObject(hMemoryDC, tmpBitmap);
+
memset(&textMetric, 0, sizeof(TEXTMETRIC));
err = GetTextMetrics(hMemoryDC, &textMetric);
if (err == 0) {
@@ -334,7 +344,7 @@
if (hBitmap == NULL) {
FREE_AND_RETURN;
}
- hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
+ SelectObject(hMemoryDC, hBitmap);
/* Fill in black */
rect.left = 0;
@@ -478,6 +488,7 @@
ReleaseDC(hWnd, hDesktopDC);
DeleteObject(hMemoryDC);
DeleteObject(hBitmap);
+ DeleteObject(tmpBitmap);
return ptr_to_jlong(glyphInfo);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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
+ * 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
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.function.Consumer;
+
+/**
+ * Implemented by classes that offer an asynchronous interface.
+ *
+ * PlainHttpConnection, AsyncSSLConnection AsyncSSLDelegate.
+ *
+ * setAsyncCallbacks() is called to set the callback for reading
+ * and error notification. Reads all happen on the selector thread, which
+ * must not block.
+ *
+ * Writing uses the same write() methods as used in blocking mode.
+ * Queues are employed on the writing side to buffer data while it is waiting
+ * to be sent. This strategy relies on HTTP/2 protocol flow control to stop
+ * outgoing queue from continually growing. Writes can be initiated by the
+ * calling thread, but if socket becomes full then the queue is emptied by
+ * the selector thread
+ *
+ */
+interface AsyncConnection {
+
+ /**
+ * Enables asynchronous sending and receiving mode. The given async
+ * receiver will receive all incoming data. asyncInput() will be called
+ * to trigger reads. asyncOutput() will be called to drive writes.
+ *
+ * The errorReceiver callback must be called when any fatal exception
+ * occurs. Connection is assumed to be closed afterwards.
+ *
+ * @param asyncReceiver
+ * @param errorReceiver
+ */
+ void setAsyncCallbacks(
+ Consumer<ByteBuffer> asyncReceiver,
+ Consumer<Throwable> errorReceiver);
+
+ /**
+ * Does whatever is required to start reading. Usually registers
+ * an event with the selector thread.
+ */
+ void startReading();
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java Fri May 06 06:23:30 2016 -0700
@@ -25,24 +25,27 @@
package java.net.http;
import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
/**
* Event handling interface from HttpClientImpl's selector.
*
- * <p> If blockingChannel is true, then the channel will be put in blocking
+ * If BLOCKING is set, then the channel will be put in blocking
* mode prior to handle() being called. If false, then it remains non-blocking.
+ *
+ * If REPEATING is set then the event is not cancelled after being posted.
*/
abstract class AsyncEvent {
- /**
- * Implement this if channel should be made blocking before calling handle()
- */
- public interface Blocking { }
+ public static final int BLOCKING = 0x1; // non blocking if not set
+ public static final int REPEATING = 0x2; // one off event if not set
- /**
- * Implement this if channel should remain non-blocking before calling handle()
- */
- public interface NonBlocking { }
+ protected final int flags;
+
+ AsyncEvent(int flags) {
+ this.flags = flags;
+ }
/** Returns the channel */
public abstract SelectableChannel channel();
@@ -55,4 +58,12 @@
/** Called when selector is shutting down. Abort all exchanges. */
public abstract void abort();
+
+ public boolean blocking() {
+ return (flags & BLOCKING) != 0;
+ }
+
+ public boolean repeating() {
+ return (flags & REPEATING) != 0;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,129 @@
+/*
+ * 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
+ * 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
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+
+/**
+ * Asynchronous version of SSLConnection.
+ */
+class AsyncSSLConnection extends HttpConnection implements AsyncConnection {
+ final AsyncSSLDelegate sslDelegate;
+ final PlainHttpConnection delegate;
+
+ AsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) {
+ super(addr, client);
+ delegate = new PlainHttpConnection(addr, client);
+ sslDelegate = new AsyncSSLDelegate(delegate, client, ap);
+ }
+
+ @Override
+ public void connect() throws IOException, InterruptedException {
+ delegate.connect();
+ }
+
+ @Override
+ public CompletableFuture<Void> connectAsync() {
+ return delegate.connectAsync();
+ }
+
+ @Override
+ boolean connected() {
+ return delegate.connected();
+ }
+
+ @Override
+ boolean isSecure() {
+ return true;
+ }
+
+ @Override
+ boolean isProxied() {
+ return false;
+ }
+
+ @Override
+ SocketChannel channel() {
+ return delegate.channel();
+ }
+
+ @Override
+ ConnectionPool.CacheKey cacheKey() {
+ return ConnectionPool.cacheKey(address, null);
+ }
+
+ @Override
+ synchronized long write(ByteBuffer[] buffers, int start, int number) throws IOException {
+ ByteBuffer[] bufs = Utils.reduce(buffers, start, number);
+ long n = Utils.remaining(bufs);
+ sslDelegate.write(bufs);
+ return n;
+ }
+
+ @Override
+ long write(ByteBuffer buffer) throws IOException {
+ long n = buffer.remaining();
+ sslDelegate.write(buffer);
+ return n;
+ }
+
+ @Override
+ public void close() {
+ Utils.close(sslDelegate, delegate.channel());
+ }
+
+ @Override
+ public void setAsyncCallbacks(Consumer<ByteBuffer> asyncReceiver, Consumer<Throwable> errorReceiver) {
+ sslDelegate.setAsyncCallbacks(asyncReceiver, errorReceiver);
+ delegate.setAsyncCallbacks(sslDelegate::lowerRead, errorReceiver);
+ }
+
+ // Blocking read functions not used here
+
+ @Override
+ protected ByteBuffer readImpl(int length) throws IOException {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ protected int readImpl(ByteBuffer buffer) throws IOException {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ CompletableFuture<Void> whenReceivingResponse() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void startReading() {
+ delegate.startReading();
+ sslDelegate.startReading();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,598 @@
+/*
+ * 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
+ * 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
+ */
+package java.net.http;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+import static javax.net.ssl.SSLEngineResult.Status.*;
+import javax.net.ssl.*;
+import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*;
+
+/**
+ * Asynchronous wrapper around SSLEngine. send and receive is fully non
+ * blocking. When handshaking is required, a thread is created to perform
+ * the handshake and application level sends do not take place during this time.
+ *
+ * Is implemented using queues and functions operating on the receiving end
+ * of each queue.
+ *
+ * Application writes to:
+ * ||
+ * \/
+ * appOutputQ
+ * ||
+ * \/
+ * appOutputQ read by "upperWrite" method which does SSLEngine.wrap
+ * and writes to
+ * ||
+ * \/
+ * channelOutputQ
+ * ||
+ * \/
+ * channelOutputQ is read by "lowerWrite" method which is invoked from
+ * OP_WRITE events on the socket (from selector thread)
+ *
+ * Reading side is as follows
+ * --------------------------
+ *
+ * "upperRead" method reads off channelInputQ and calls SSLEngine.unwrap and
+ * when decrypted data is returned, it is passed to the user's Consumer<ByteBuffer>
+ * /\
+ * ||
+ * channelInputQ
+ * /\
+ * ||
+ * "lowerRead" method puts buffers into channelInputQ. It is invoked from
+ * OP_READ events from the selector.
+ *
+ * Whenever handshaking is required, the doHandshaking() method is called
+ * which creates a thread to complete the handshake. It takes over the
+ * channelInputQ from upperRead, and puts outgoing packets on channelOutputQ.
+ * Selector events are delivered to lowerRead and lowerWrite as normal.
+ *
+ * Errors
+ *
+ * Any exception thrown by the engine or channel, causes all Queues to be closed
+ * the channel to be closed, and the error is reported to the user's
+ * Consumer<Throwable>
+ */
+public class AsyncSSLDelegate implements Closeable, AsyncConnection {
+
+ // outgoing buffers put in this queue first and may remain here
+ // while SSL handshaking happening.
+ final Queue<ByteBuffer> appOutputQ;
+
+ // queue of wrapped ByteBuffers waiting to be sent on socket channel
+ //final Queue<ByteBuffer> channelOutputQ;
+
+ // Bytes read into this queue before being unwrapped. Backup on this
+ // Q should only happen when the engine is stalled due to delegated tasks
+ final Queue<ByteBuffer> channelInputQ;
+
+ // input occurs through the read() method which is expected to be called
+ // when the selector signals some data is waiting to be read. All incoming
+ // handshake data is handled in this method, which means some calls to
+ // read() may return zero bytes of user data. This is not a sign of spinning,
+ // just that the handshake mechanics are being executed.
+
+ final SSLEngine engine;
+ final SSLParameters sslParameters;
+ //final SocketChannel chan;
+ final HttpConnection lowerOutput;
+ final HttpClientImpl client;
+ final ExecutorService executor;
+ final BufferHandler bufPool;
+ Consumer<ByteBuffer> receiver;
+ Consumer<Throwable> errorHandler;
+ // Locks.
+ final Object reader = new Object();
+ final Object writer = new Object();
+ // synchronizing handshake state
+ final Object handshaker = new Object();
+ // flag set when reader or writer is blocked waiting for handshake to finish
+ boolean writerBlocked;
+ boolean readerBlocked;
+
+ // some thread is currently doing the handshake
+ boolean handshaking;
+
+ // alpn[] may be null. upcall is callback which receives incoming decoded bytes off socket
+
+ AsyncSSLDelegate(HttpConnection lowerOutput, HttpClientImpl client, String[] alpn)
+ {
+ SSLContext context = client.sslContext();
+ executor = client.executorService();
+ bufPool = client;
+ appOutputQ = new Queue<>();
+ appOutputQ.registerPutCallback(this::upperWrite);
+ //channelOutputQ = new Queue<>();
+ //channelOutputQ.registerPutCallback(this::lowerWrite);
+ engine = context.createSSLEngine();
+ engine.setUseClientMode(true);
+ SSLParameters sslp = client.sslParameters().orElse(null);
+ if (sslp == null) {
+ sslp = context.getSupportedSSLParameters();
+ //sslp = context.getDefaultSSLParameters();
+ //printParams(sslp);
+ }
+ sslParameters = Utils.copySSLParameters(sslp);
+ if (alpn != null) {
+ sslParameters.setApplicationProtocols(alpn);
+ Log.logSSL("Setting application protocols: " + Arrays.toString(alpn));
+ } else {
+ Log.logSSL("No application protocols proposed");
+ }
+ engine.setSSLParameters(sslParameters);
+ engine.setEnabledCipherSuites(sslp.getCipherSuites());
+ engine.setEnabledProtocols(sslp.getProtocols());
+ this.lowerOutput = lowerOutput;
+ this.client = client;
+ this.channelInputQ = new Queue<>();
+ this.channelInputQ.registerPutCallback(this::upperRead);
+ }
+
+ /**
+ * Put buffers to appOutputQ, and call upperWrite() if q was empty.
+ *
+ * @param src
+ */
+ public void write(ByteBuffer[] src) throws IOException {
+ appOutputQ.putAll(src);
+ }
+
+ public void write(ByteBuffer buf) throws IOException {
+ ByteBuffer[] a = new ByteBuffer[1];
+ a[0] = buf;
+ write(a);
+ }
+
+ @Override
+ public void close() {
+ Utils.close(appOutputQ, channelInputQ, lowerOutput);
+ }
+
+ /**
+ * Attempts to wrap buffers from appOutputQ and place them on the
+ * channelOutputQ for writing. If handshaking is happening, then the
+ * process stalls and last buffers taken off the appOutputQ are put back
+ * into it until handshaking completes.
+ *
+ * This same method is called to try and resume output after a blocking
+ * handshaking operation has completed.
+ */
+ private void upperWrite() {
+ try {
+ EngineResult r = null;
+ ByteBuffer[] buffers = appOutputQ.pollAll(Utils.EMPTY_BB_ARRAY);
+ int bytes = Utils.remaining(buffers);
+ while (bytes > 0) {
+ synchronized (writer) {
+ r = wrapBuffers(buffers);
+ int bytesProduced = r.bytesProduced();
+ int bytesConsumed = r.bytesConsumed();
+ bytes -= bytesConsumed;
+ if (bytesProduced > 0) {
+ // pass destination buffer to channelOutputQ.
+ lowerOutput.write(r.destBuffer);
+ }
+ synchronized (handshaker) {
+ if (r.handshaking()) {
+ // handshaking is happening or is needed
+ // so we put the buffers back on Q to process again
+ // later. It's possible that some may have already
+ // been processed, which is ok.
+ appOutputQ.pushbackAll(buffers);
+ writerBlocked = true;
+ if (!handshaking()) {
+ // execute the handshake in another thread.
+ // This method will be called again to resume sending
+ // later
+ doHandshake(r);
+ }
+ return;
+ }
+ }
+ }
+ }
+ returnBuffers(buffers);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ close();
+ }
+ }
+
+ private void doHandshake(EngineResult r) {
+ handshaking = true;
+ channelInputQ.registerPutCallback(null);
+ executor.execute(() -> {
+ try {
+ doHandshakeImpl(r);
+ channelInputQ.registerPutCallback(this::upperRead);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ close();
+ }
+ });
+ }
+
+ private void returnBuffers(ByteBuffer[] bufs) {
+ for (ByteBuffer buf : bufs)
+ client.returnBuffer(buf);
+ }
+
+ /**
+ * Return true if some thread is currently doing the handshake
+ *
+ * @return
+ */
+ boolean handshaking() {
+ synchronized(handshaker) {
+ return handshaking;
+ }
+ }
+
+ /**
+ * Executes entire handshake in calling thread.
+ * Returns after handshake is completed or error occurs
+ * @param r
+ * @throws IOException
+ */
+ private void doHandshakeImpl(EngineResult r) throws IOException {
+ while (true) {
+ SSLEngineResult.HandshakeStatus status = r.handshakeStatus();
+ if (status == NEED_TASK) {
+ LinkedList<Runnable> tasks = obtainTasks();
+ for (Runnable task : tasks)
+ task.run();
+ r = handshakeWrapAndSend();
+ } else if (status == NEED_WRAP) {
+ r = handshakeWrapAndSend();
+ } else if (status == NEED_UNWRAP) {
+ r = handshakeReceiveAndUnWrap();
+ }
+ if (!r.handshaking())
+ break;
+ }
+ boolean dowrite = false;
+ boolean doread = false;
+ // Handshake is finished. Now resume reading and/or writing
+ synchronized(handshaker) {
+ handshaking = false;
+ if (writerBlocked) {
+ writerBlocked = false;
+ dowrite = true;
+ }
+ if (readerBlocked) {
+ readerBlocked = false;
+ doread = true;
+ }
+ }
+ if (dowrite)
+ upperWrite();
+ if (doread)
+ upperRead();
+ }
+
+ // acknowledge a received CLOSE request from peer
+ void doClosure() throws IOException {
+ //while (!wrapAndSend(emptyArray))
+ //;
+ }
+
+ LinkedList<Runnable> obtainTasks() {
+ LinkedList<Runnable> l = new LinkedList<>();
+ Runnable r;
+ while ((r = engine.getDelegatedTask()) != null)
+ l.add(r);
+ return l;
+ }
+
+ @Override
+ public synchronized void setAsyncCallbacks(Consumer<ByteBuffer> asyncReceiver, Consumer<Throwable> errorReceiver) {
+ this.receiver = asyncReceiver;
+ this.errorHandler = errorReceiver;
+ }
+
+ @Override
+ public void startReading() {
+ // maybe this class does not need to implement AsyncConnection
+ }
+
+ static class EngineResult {
+ ByteBuffer destBuffer;
+ ByteBuffer srcBuffer;
+ SSLEngineResult result;
+ Throwable t;
+
+ boolean handshaking() {
+ SSLEngineResult.HandshakeStatus s = result.getHandshakeStatus();
+ return s != FINISHED && s != NOT_HANDSHAKING;
+ }
+
+ int bytesConsumed() {
+ return result.bytesConsumed();
+ }
+
+ int bytesProduced() {
+ return result.bytesProduced();
+ }
+
+ Throwable exception() {
+ return t;
+ }
+
+ SSLEngineResult.HandshakeStatus handshakeStatus() {
+ return result.getHandshakeStatus();
+ }
+
+ SSLEngineResult.Status status() {
+ return result.getStatus();
+ }
+ }
+
+ EngineResult handshakeWrapAndSend() throws IOException {
+ EngineResult r = wrapBuffer(Utils.EMPTY_BYTEBUFFER);
+ if (r.bytesProduced() > 0) {
+ lowerOutput.write(r.destBuffer);
+ }
+ return r;
+ }
+
+ // called during handshaking. It blocks until a complete packet
+ // is available, unwraps it and returns.
+ EngineResult handshakeReceiveAndUnWrap() throws IOException {
+ ByteBuffer buf = channelInputQ.take();
+ while (true) {
+ // block waiting for input
+ EngineResult r = unwrapBuffer(buf);
+ SSLEngineResult.Status status = r.status();
+ if (status == BUFFER_UNDERFLOW) {
+ // wait for another buffer to arrive
+ ByteBuffer buf1 = channelInputQ.take();
+ buf = combine (buf, buf1);
+ continue;
+ }
+ // OK
+ // theoretically possible we could receive some user data
+ if (r.bytesProduced() > 0) {
+ receiver.accept(r.destBuffer);
+ }
+ if (!buf.hasRemaining())
+ return r;
+ }
+ }
+
+ EngineResult wrapBuffer(ByteBuffer src) throws SSLException {
+ ByteBuffer[] bufs = new ByteBuffer[1];
+ bufs[0] = src;
+ return wrapBuffers(bufs);
+ }
+
+ EngineResult wrapBuffers(ByteBuffer[] src) throws SSLException {
+ EngineResult r = new EngineResult();
+ ByteBuffer dst = bufPool.getBuffer();
+ while (true) {
+ r.result = engine.wrap(src, dst);
+ switch (r.result.getStatus()) {
+ case BUFFER_OVERFLOW:
+ dst = getPacketBuffer();
+ break;
+ case CLOSED:
+ case OK:
+ dst.flip();
+ r.destBuffer = dst;
+ return r;
+ case BUFFER_UNDERFLOW:
+ // underflow handled externally
+ bufPool.returnBuffer(dst);
+ return r;
+ default:
+ assert false;
+ }
+ }
+ }
+
+ EngineResult unwrapBuffer(ByteBuffer srcbuf) throws IOException {
+ EngineResult r = new EngineResult();
+ r.srcBuffer = srcbuf;
+
+ ByteBuffer dst = bufPool.getBuffer();
+ while (true) {
+ r.result = engine.unwrap(srcbuf, dst);
+ switch (r.result.getStatus()) {
+ case BUFFER_OVERFLOW:
+ // dest buffer not big enough. Reallocate
+ int oldcap = dst.capacity();
+ dst = getApplicationBuffer();
+ assert dst.capacity() > oldcap;
+ break;
+ case CLOSED:
+ doClosure();
+ throw new IOException("Engine closed");
+ case BUFFER_UNDERFLOW:
+ bufPool.returnBuffer(dst);
+ return r;
+ case OK:
+ dst.flip();
+ r.destBuffer = dst;
+ return r;
+ }
+ }
+ }
+
+ /**
+ * Asynchronous read input. Call this when selector fires.
+ * Unwrap done in upperRead because it also happens in
+ * doHandshake() when handshake taking place
+ */
+ public void lowerRead(ByteBuffer buffer) {
+ try {
+ channelInputQ.put(buffer);
+ } catch (Throwable t) {
+ close();
+ errorHandler.accept(t);
+ }
+ }
+
+ public void upperRead() {
+ EngineResult r;
+ ByteBuffer srcbuf;
+ synchronized (reader) {
+ try {
+ srcbuf = channelInputQ.poll();
+ if (srcbuf == null) {
+ return;
+ }
+ while (true) {
+ r = unwrapBuffer(srcbuf);
+ switch (r.result.getStatus()) {
+ case BUFFER_UNDERFLOW:
+ // Buffer too small. Need to combine with next buf
+ ByteBuffer nextBuf = channelInputQ.poll();
+ if (nextBuf == null) {
+ // no data available. push buffer back until more data available
+ channelInputQ.pushback(srcbuf);
+ return;
+ } else {
+ srcbuf = combine(srcbuf, nextBuf);
+ }
+ break;
+ case OK:
+ // check for any handshaking work
+ synchronized (handshaker) {
+ if (r.handshaking()) {
+ // handshaking is happening or is needed
+ // so we put the buffer back on Q to process again
+ // later.
+ channelInputQ.pushback(srcbuf);
+ readerBlocked = true;
+ if (!handshaking()) {
+ // execute the handshake in another thread.
+ // This method will be called again to resume sending
+ // later
+ doHandshake(r);
+ }
+ return;
+ }
+ }
+ ByteBuffer dst = r.destBuffer;
+ if (dst.hasRemaining()) {
+ receiver.accept(dst);
+ }
+ }
+ if (srcbuf.hasRemaining()) {
+ continue;
+ }
+ srcbuf = channelInputQ.poll();
+ if (srcbuf == null) {
+ return;
+ }
+ }
+ } catch (Throwable t) {
+ Utils.close(lowerOutput);
+ errorHandler.accept(t);
+ }
+ }
+ }
+
+ /**
+ * Get a new buffer that is the right size for application buffers.
+ *
+ * @return
+ */
+ ByteBuffer getApplicationBuffer() {
+ SSLSession session = engine.getSession();
+ int appBufsize = session.getApplicationBufferSize();
+ bufPool.setMinBufferSize(appBufsize);
+ return bufPool.getBuffer(appBufsize);
+ }
+
+ ByteBuffer getPacketBuffer() {
+ SSLSession session = engine.getSession();
+ int packetBufSize = session.getPacketBufferSize();
+ bufPool.setMinBufferSize(packetBufSize);
+ return bufPool.getBuffer(packetBufSize);
+ }
+
+ ByteBuffer combine(ByteBuffer buf1, ByteBuffer buf2) {
+ int avail1 = buf1.capacity() - buf1.remaining();
+ if (buf2.remaining() < avail1) {
+ buf1.compact();
+ buf1.put(buf2);
+ buf1.flip();
+ return buf1;
+ }
+ int newsize = buf1.remaining() + buf2.remaining();
+ ByteBuffer newbuf = bufPool.getBuffer(newsize);
+ newbuf.put(buf1);
+ newbuf.put(buf2);
+ newbuf.flip();
+ return newbuf;
+ }
+
+ SSLParameters getSSLParameters() {
+ return sslParameters;
+ }
+
+ static void printParams(SSLParameters p) {
+ System.out.println("SSLParameters:");
+ if (p == null) {
+ System.out.println("Null params");
+ return;
+ }
+ for (String cipher : p.getCipherSuites()) {
+ System.out.printf("cipher: %s\n", cipher);
+ }
+ for (String approto : p.getApplicationProtocols()) {
+ System.out.printf("application protocol: %s\n", approto);
+ }
+ for (String protocol : p.getProtocols()) {
+ System.out.printf("protocol: %s\n", protocol);
+ }
+ if (p.getServerNames() != null)
+ for (SNIServerName sname : p.getServerNames()) {
+ System.out.printf("server name: %s\n", sname.toString());
+ }
+ }
+
+ String getSessionInfo() {
+ StringBuilder sb = new StringBuilder();
+ String application = engine.getApplicationProtocol();
+ SSLSession sess = engine.getSession();
+ String cipher = sess.getCipherSuite();
+ String protocol = sess.getProtocol();
+ sb.append("Handshake complete alpn: ")
+ .append(application)
+ .append(", Cipher: ")
+ .append(cipher)
+ .append(", Protocol: ")
+ .append(protocol);
+ return sb.toString();
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java Fri May 06 06:23:30 2016 -0700
@@ -45,7 +45,7 @@
static final int DEFAULT_RETRY_LIMIT = 3;
static final int retry_limit = Utils.getIntegerNetProperty(
- "sun.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT);
+ "java.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT);
static final int UNAUTHORIZED = 401;
static final int PROXY_UNAUTHORIZED = 407;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java Fri May 06 06:23:30 2016 -0700
@@ -27,11 +27,23 @@
import java.nio.ByteBuffer;
/**
- * Implemented by buffer pools.
+ * Implemented by buffer pools. A buffer pool has a current buffer size
+ * (number of bytes in each buffer) which may increase over time.
*/
interface BufferHandler {
- ByteBuffer getBuffer();
+ default ByteBuffer getBuffer() {
+ return getBuffer(-1);
+ }
+
+ void setMinBufferSize(int size);
+
+ /**
+ * size == -1 means return any sized buffer. Any other value means
+ * @param size
+ * @return
+ */
+ ByteBuffer getBuffer(int size);
void returnBuffer(ByteBuffer buffer);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,188 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.function.Supplier;
+
+/**
+ * Takes a List<ByteBuffer> which is assumed to contain at least one HTTP/2
+ * frame and allows it to be processed supplying bytes, ints, shorts, byte[] etc.
+ * from the list. As each ByteBuffer is consumed it is removed from the List<>.
+ *
+ * NOTE. shorts and bytes returned are UNSIGNED ints
+ *
+ * When finished processing the frame, the List may be empty or may contain
+ * partially read or unread ByteBuffers. A new ByteBufferConsumer can be
+ * created with the List<>
+ */
+class ByteBufferConsumer {
+
+ ByteBuffer currentBuffer;
+
+ final List<ByteBuffer> buffers;
+ final ListIterator<ByteBuffer> iterator;
+ final Supplier<ByteBuffer> newBufferSupplier;
+
+ ByteBufferConsumer(List<ByteBuffer> buffers,
+ Supplier<ByteBuffer> newBufferSupplier) {
+ this.buffers = buffers;
+ this.newBufferSupplier = newBufferSupplier;
+ this.iterator = buffers.listIterator();
+ if (!iterator.hasNext()) {
+ throw new IllegalArgumentException("Empty buffer list");
+ }
+ currentBuffer = iterator.next();
+ }
+
+ private void dump() {
+ int l = 0;
+ System.err.printf("ByteBufferConsumer:\n");
+ for (ByteBuffer buf : buffers) {
+ System.err.printf("\t%s\n", buf.toString());
+ l+= buf.remaining();
+ }
+ System.err.printf("BBC contains %d bytes\n", l);
+ }
+
+ private synchronized ByteBuffer getBuffer(boolean exception) throws IOException {
+ while (currentBuffer == null || !currentBuffer.hasRemaining()) {
+ if (currentBuffer != null) {
+ iterator.remove();
+ }
+ if (!iterator.hasNext()) {
+ currentBuffer = null;
+ if (exception) {
+ throw new IOException ("Connection closed unexpectedly");
+ }
+ return null;
+ }
+ currentBuffer = iterator.next();
+ }
+ return currentBuffer;
+ }
+
+ // call this to check if the data has all been consumed
+
+ public boolean consumed() {
+ try {
+ return getBuffer(false) == null;
+ } catch (IOException e) {
+ /* CAN'T HAPPEN */
+ throw new InternalError();
+ }
+ }
+
+ public int getByte() throws IOException {
+ // TODO: what to do if connection is closed. Throw NPE?
+ ByteBuffer buf = getBuffer(true);
+ return buf.get() & 0xff;
+ }
+
+ public byte[] getBytes(int n) throws IOException {
+ return getBytes(n, null);
+ }
+
+ public byte[] getBytes(int n, byte[] buf) throws IOException {
+ if (buf == null) {
+ buf = new byte[n];
+ } else if (buf.length < n) {
+ throw new IllegalArgumentException("getBytes: buffer too small");
+ }
+ int offset = 0;
+ while (n > 0) {
+ ByteBuffer b = getBuffer(true);
+ int length = Math.min(n, b.remaining());
+ b.get(buf, offset, length);
+ offset += length;
+ n -= length;
+ }
+ return buf;
+ }
+
+ public int getShort() throws IOException {
+ ByteBuffer buf = getBuffer(true);
+ int rem = buf.remaining();
+ if (rem >= 2) {
+ return buf.getShort() & 0xffff;
+ }
+ // Slow path. Not common
+ int val = 0;
+ val = (val << 8) + getByte();
+ val = (val << 8) + getByte();
+ return val;
+ }
+
+ public int getInt() throws IOException {
+ ByteBuffer buf = getBuffer(true);
+ int rem = buf.remaining();
+ if (rem >= 4) {
+ return buf.getInt();
+ }
+ // Slow path. Not common
+ int val = 0;
+ for (int nbytes = 0; nbytes < 4; nbytes++) {
+ val = (val << 8) + getByte();
+ }
+ return val;
+ }
+
+ private static final ByteBuffer[] EMPTY = new ByteBuffer[0];
+
+ /**
+ * Extracts whatever number of ByteBuffers from list to get required number
+ * of bytes. Any remaining buffers are 'tidied up' so reading can continue.
+ */
+ public ByteBuffer[] getBuffers(int bytecount) throws IOException {
+ LinkedList<ByteBuffer> l = new LinkedList<>();
+ while (bytecount > 0) {
+ ByteBuffer buffer = getBuffer(true);
+ int remaining = buffer.remaining();
+ if (remaining > bytecount) {
+ int difference = remaining - bytecount;
+ // split
+ ByteBuffer newb = newBufferSupplier.get();
+ newb.clear();
+ int limit = buffer.limit();
+ buffer.limit(limit - difference);
+ newb.put(buffer);
+ newb.flip();
+ buffer.limit(limit);
+ l.add(newb);
+ bytecount = 0;
+ } else {
+ l.add(buffer);
+ currentBuffer = null;
+ iterator.remove();
+ bytecount -= remaining;
+ }
+ }
+ return l.toArray(EMPTY);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,136 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+/**
+ * Manages a ByteBuffer[] for writing frames into for output. The last
+ * ByteBuffer in the list is always unflipped (able to receive more bytes for
+ * sending) until getBufferArray() is called, which calls finish().
+ *
+ * This allows multiple frames to be written to the same BBG.
+ *
+ * Buffers added with addByteBuffer() must be already flipped.
+ */
+class ByteBufferGenerator {
+
+ ByteBuffer currentBuffer;
+ // source is assumed to always return the same sized buffer
+ final BufferHandler pool;
+ final ArrayList<ByteBuffer> buflist;
+ final int bufsize;
+ boolean finished;
+
+ ByteBufferGenerator(BufferHandler pool) {
+ this.buflist = new ArrayList<>();
+ this.pool = pool;
+ this.currentBuffer = pool.getBuffer();
+ this.bufsize = currentBuffer.capacity();
+ }
+
+ private static final ByteBuffer[] EMPTY = new ByteBuffer[0];
+
+ public ByteBuffer[] getBufferArray() {
+ finish();
+ return buflist.toArray(EMPTY);
+ }
+
+ public ArrayList<ByteBuffer> getBufferList() {
+ finish();
+ return buflist;
+ }
+
+ private synchronized void finish() {
+ if (finished) {
+ return;
+ }
+ finished = true;
+ currentBuffer.flip();
+ if (currentBuffer.hasRemaining()) {
+ buflist.add(currentBuffer);
+ } else {
+ pool.returnBuffer(currentBuffer);
+ }
+ }
+
+ // only used for SettingsFrame: offset is number of bytes to
+ // ignore at start (we only want the payload of the settings frame)
+ public byte[] asByteArray(int offset) {
+ ByteBuffer[] bufs = getBufferArray();
+ int size = 0;
+ for (ByteBuffer buf : bufs) {
+ size += buf.remaining();
+ }
+ byte[] bytes = new byte[size-offset];
+ int pos = 0;
+ for (ByteBuffer buf : bufs) {
+ int rem = buf.remaining();
+ int ignore = Math.min(rem, offset);
+ buf.position(buf.position()+ignore);
+ rem -= ignore;
+ offset -= ignore;
+ buf.get(bytes, pos, rem);
+ pos += rem;
+ }
+ return bytes;
+ }
+
+ ByteBuffer getBuffer(long n) {
+ if (currentBuffer.remaining() < n) {
+ getNewBuffer();
+ if (n > currentBuffer.capacity()) {
+ throw new IllegalArgumentException("requested buffer too large");
+ }
+ }
+ return currentBuffer;
+ }
+
+ void getNewBuffer() {
+ currentBuffer.flip();
+ if (currentBuffer.hasRemaining()) {
+ buflist.add(currentBuffer);
+ } else {
+ pool.returnBuffer(currentBuffer);
+ }
+ currentBuffer = pool.getBuffer();
+ }
+
+ void addByteBuffer(ByteBuffer buf) {
+ getNewBuffer();
+ buflist.add(buf);
+ }
+
+ void addPadding(int length) {
+ while (length > 0) {
+ int n = Math.min(length, bufsize);
+ ByteBuffer b = getBuffer(n);
+ // TODO: currently zeroed?
+ b.position(b.position() + n);
+ length -= n;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,159 @@
+/*
+ * 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
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+// The purpose of this class is to separate charset-related tasks from the main
+// WebSocket logic, simplifying where possible.
+//
+// * Coders hide the differences between coding and flushing stages on the
+// API level
+// * Verifier abstracts the way the verification is performed
+// (spoiler: it's a decoding into a throw-away buffer)
+//
+// Coding methods throw exceptions instead of returning coding result denoting
+// errors, since any kind of handling and recovery is not expected.
+final class CharsetToolkit {
+
+ private CharsetToolkit() { }
+
+ static final class Verifier {
+
+ private final CharsetDecoder decoder = UTF_8.newDecoder();
+ // A buffer used to check validity of UTF-8 byte stream by decoding it.
+ // The contents of this buffer are never used.
+ // The size is arbitrary, though it should probably be chosen from the
+ // performance perspective since it affects the total number of calls to
+ // decoder.decode() and amount of work in each of these calls
+ private final CharBuffer blackHole = CharBuffer.allocate(1024);
+
+ void verify(ByteBuffer in, boolean endOfInput)
+ throws CharacterCodingException {
+ while (true) {
+ // Since decoder.flush() cannot produce an error, it's not
+ // helpful for verification. Therefore this step is skipped.
+ CoderResult r = decoder.decode(in, blackHole, endOfInput);
+ if (r.isOverflow()) {
+ blackHole.clear();
+ } else if (r.isUnderflow()) {
+ break;
+ } else if (r.isError()) {
+ r.throwException();
+ } else {
+ // Should not happen
+ throw new InternalError();
+ }
+ }
+ }
+
+ Verifier reset() {
+ decoder.reset();
+ return this;
+ }
+ }
+
+ static final class Encoder {
+
+ private final CharsetEncoder encoder = UTF_8.newEncoder();
+ private boolean coding = true;
+
+ CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput)
+ throws CharacterCodingException {
+
+ if (coding) {
+ CoderResult r = encoder.encode(in, out, endOfInput);
+ if (r.isOverflow()) {
+ return r;
+ } else if (r.isUnderflow()) {
+ if (endOfInput) {
+ coding = false;
+ } else {
+ return r;
+ }
+ } else if (r.isError()) {
+ r.throwException();
+ } else {
+ // Should not happen
+ throw new InternalError();
+ }
+ }
+ assert !coding;
+ return encoder.flush(out);
+ }
+
+ Encoder reset() {
+ coding = true;
+ encoder.reset();
+ return this;
+ }
+ }
+
+ static CharBuffer decode(ByteBuffer in) throws CharacterCodingException {
+ return UTF_8.newDecoder().decode(in);
+ }
+
+ static final class Decoder {
+
+ private final CharsetDecoder decoder = UTF_8.newDecoder();
+ private boolean coding = true; // Either coding or flushing
+
+ CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
+ throws CharacterCodingException {
+
+ if (coding) {
+ CoderResult r = decoder.decode(in, out, endOfInput);
+ if (r.isOverflow()) {
+ return r;
+ } else if (r.isUnderflow()) {
+ if (endOfInput) {
+ coding = false;
+ } else {
+ return r;
+ }
+ } else if (r.isError()) {
+ r.throwException();
+ } else {
+ // Should not happen
+ throw new InternalError();
+ }
+ }
+ assert !coding;
+ return decoder.flush(out);
+ }
+
+ Decoder reset() {
+ coding = true;
+ decoder.reset();
+ return this;
+ }
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java Fri May 06 06:23:30 2016 -0700
@@ -35,7 +35,7 @@
class ConnectionPool {
static final long KEEP_ALIVE = Utils.getIntegerNetProperty(
- "sun.net.httpclient.keepalive.timeout", 1200); // seconds
+ "java.net.httpclient.keepalive.timeout", 1200); // seconds
// Pools of idle connections
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,59 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+
+class ContinuationFrame extends HeaderFrame {
+
+ public static final int TYPE = 0x9;
+
+ ContinuationFrame() {
+ type = TYPE;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ headerBlocks = bc.getBuffers(length);
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ for (int i=0; i<headerBlocks.length; i++) {
+ bg.addByteBuffer(headerBlocks[i]);
+ }
+ }
+
+ @Override
+ public boolean endHeaders() {
+ return getFlag(END_HEADERS);
+ }
+
+ @Override
+ void computeLength() {
+ length = headerLength;
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java Fri May 06 06:23:30 2016 -0700
@@ -44,7 +44,7 @@
@Override
public void request(HttpRequestImpl r) throws IOException {
Map<String,List<String>> userheaders, cookies;
- userheaders = r.getUserHeaders().directMap();
+ userheaders = r.getUserHeaders().map();
cookies = cookieMan.get(r.uri(), userheaders);
// add the returned cookies
HttpHeadersImpl systemHeaders = r.getSystemHeaders();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class DataFrame extends Http2Frame {
+
+ public final static int TYPE = 0x0;
+
+ DataFrame() {
+ type = TYPE;
+ }
+
+ // Flags
+ public static final int END_STREAM = 0x1;
+ public static final int PADDED = 0x8;
+
+ int padLength;
+ int dataLength;
+ ByteBuffer[] data;
+
+ public void setData(ByteBuffer[] data) {
+ this.data = data;
+ setDataLength();
+ }
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case END_STREAM:
+ return "END_STREAM";
+ case PADDED:
+ return "PADDED";
+ }
+ return super.flagAsString(flag);
+ }
+
+ public synchronized void setData(ByteBuffer data) {
+ ByteBuffer[] bb;
+ if (data == null) {
+ bb = new ByteBuffer[0];
+ } else {
+ bb = new ByteBuffer[1];
+ bb[0] = data;
+ }
+ setData(bb);
+ }
+
+ public synchronized ByteBuffer[] getData() {
+ return data;
+ }
+
+ private void setDataLength() {
+ int len = 0;
+ for (ByteBuffer buf : data) {
+ len += buf.remaining();
+ }
+ dataLength = len;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if ((flags & PADDED) != 0) {
+ padLength = bc.getByte();
+ dataLength = length - (padLength + 1);
+ } else {
+ dataLength = length;
+ }
+ data = bc.getBuffers(dataLength);
+ }
+
+ int getPadLength() {
+ return padLength;
+ }
+
+ int getDataLength() {
+ return dataLength;
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ if ((flags & PADDED) != 0) {
+ ByteBuffer buf = bg.getBuffer(1);
+ buf.put((byte)getPadLength());
+ }
+ for (int i=0; i<data.length; i++) {
+ bg.addByteBuffer(data[i]);
+ }
+ if ((flags & PADDED) != 0) {
+ bg.addPadding(padLength);
+ }
+ }
+
+ @Override
+ void computeLength() {
+ length = dataLength;
+ if ((flags & PADDED) != 0) {
+ length += (1 + padLength);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ErrorFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+abstract class ErrorFrame extends Http2Frame {
+
+ // error codes
+ public static final int NO_ERROR = 0x0;
+ public static final int PROTOCOL_ERROR = 0x1;
+ public static final int INTERNAL_ERROR = 0x2;
+ public static final int FLOW_CONTROL_ERROR = 0x3;
+ public static final int SETTINGS_TIMEOUT = 0x4;
+ public static final int STREAM_CLOSED = 0x5;
+ public static final int FRAME_SIZE_ERROR = 0x6;
+ public static final int REFUSED_STREAM = 0x7;
+ public static final int CANCEL = 0x8;
+ public static final int COMPRESSION_ERROR = 0x9;
+ public static final int CONNECT_ERROR = 0xa;
+ public static final int ENHANCE_YOUR_CALM = 0xb;
+ public static final int INADEQUATE_SECURITY = 0xc;
+ public static final int HTTP_1_1_REQUIRED = 0xd;
+ static final int LAST_ERROR = 0xd;
+
+ static final String[] errorStrings = {
+ "Not an error",
+ "Protocol error",
+ "Internal error",
+ "Flow control error",
+ "Settings timeout",
+ "Stream is closed",
+ "Frame size error",
+ "Stream not processed",
+ "Stream cancelled",
+ "Compression state not updated",
+ "TCP Connection error on CONNECT",
+ "Processing capacity exceeded",
+ "Negotiated TLS parameters not acceptable",
+ "Use HTTP/1.1 for request"
+ };
+
+ public static String stringForCode(int code) {
+ if (code < 0)
+ throw new IllegalArgumentException();
+
+ if (code > LAST_ERROR) {
+ return "Error: " + Integer.toString(code);
+ } else {
+ return errorStrings[code];
+ }
+ }
+
+ int errorCode;
+
+ @Override
+ public String toString() {
+ return super.toString() + " Error: " + stringForCode(errorCode);
+ }
+
+ public int getErrorCode() {
+ return this.errorCode;
+ }
+
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java Fri May 06 06:23:30 2016 -0700
@@ -128,7 +128,7 @@
}
}
- HttpResponseImpl responseImpl0(HttpConnection connection)
+ private HttpResponseImpl responseImpl0(HttpConnection connection)
throws IOException, InterruptedException
{
exchImpl = ExchangeImpl.get(this, connection);
@@ -136,7 +136,7 @@
request.addSystemHeader("Expect", "100-Continue");
exchImpl.sendHeadersOnly();
HttpResponseImpl resp = exchImpl.getResponse();
- logResponse(resp);
+ Utils.logResponse(resp);
if (resp.statusCode() != 100) {
return resp;
}
@@ -145,7 +145,7 @@
} else {
exchImpl.sendRequest();
HttpResponseImpl resp = exchImpl.getResponse();
- logResponse(resp);
+ Utils.logResponse(resp);
return checkForUpgrade(resp, exchImpl);
}
}
@@ -163,9 +163,7 @@
}
SecurityException e = securityCheck(acc);
if (e != null) {
- CompletableFuture<HttpResponseImpl> cf = new CompletableFuture<>();
- cf.completeExceptionally(e);
- return cf;
+ return CompletableFuture.failedFuture(e);
}
if (permissions.size() > 0) {
return AccessController.doPrivileged(
@@ -182,9 +180,7 @@
try {
exchImpl = ExchangeImpl.get(this, connection);
} catch (IOException | InterruptedException e) {
- CompletableFuture<HttpResponseImpl> cf = new CompletableFuture<>();
- cf.completeExceptionally(e);
- return cf;
+ return CompletableFuture.failedFuture(e);
}
if (request.expectContinue()) {
request.addSystemHeader("Expect", "100-Continue");
@@ -200,23 +196,19 @@
return exchImpl.sendBodyAsync()
.thenCompose(exchImpl::getResponseAsync)
.thenApply((r) -> {
- logResponse(r);
+ Utils.logResponse(r);
return r;
});
} else {
Exchange.this.response = r1;
- logResponse(r1);
+ Utils.logResponse(r1);
return CompletableFuture.completedFuture(r1);
}
});
} else {
return exchImpl
- .sendHeadersAsync()
- .thenCompose((Void v) -> {
- // send body and get response at same time
- return exchImpl.sendBodyAsync()
- .thenCompose(exchImpl::getResponseAsync);
- })
+ .sendRequestAsync()
+ .thenCompose(exchImpl::getResponseAsync)
.thenCompose((HttpResponseImpl r1) -> {
int rcode = r1.statusCode();
CompletableFuture<HttpResponseImpl> cf =
@@ -225,13 +217,13 @@
return cf;
} else {
Exchange.this.response = r1;
- logResponse(r1);
+ Utils.logResponse(r1);
return CompletableFuture.completedFuture(r1);
}
})
.thenApply((HttpResponseImpl response) -> {
this.response = response;
- logResponse(response);
+ Utils.logResponse(response);
return response;
});
}
@@ -254,9 +246,9 @@
client.client2(),
this)
.thenCompose((Http2Connection c) -> {
+ c.putConnection();
Stream s = c.getStream(1);
exchImpl = s;
- c.putConnection();
return s.getResponseAsync(null);
})
);
@@ -294,21 +286,6 @@
}
- private void logResponse(HttpResponseImpl r) {
- if (!Log.requests())
- return;
- StringBuilder sb = new StringBuilder();
- String method = r.request().method();
- URI uri = r.uri();
- String uristring = uri == null ? "" : uri.toString();
- sb.append('(')
- .append(method)
- .append(" ")
- .append(uristring)
- .append(") ")
- .append(Integer.toString(r.statusCode()));
- Log.logResponse(sb.toString());
- }
<T> CompletableFuture<T> responseBodyAsync(HttpResponse.BodyProcessor<T> processor) {
return exchImpl.responseBodyAsync(processor);
@@ -352,9 +329,9 @@
}
String method = request.method();
- HttpHeadersImpl userHeaders = request.getUserHeaders();
+ HttpHeaders userHeaders = request.getUserHeaders();
URI u = getURIForSecurityCheck();
- URLPermission p = Utils.getPermission(u, method, userHeaders.directMap());
+ URLPermission p = Utils.getPermission(u, method, userHeaders.map());
try {
assert acc != null;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java Fri May 06 06:23:30 2016 -0700
@@ -39,7 +39,9 @@
List<HeaderFilter> l = new LinkedList<>();
for (Class<? extends HeaderFilter> clazz : filterClasses) {
try {
- l.add(clazz.newInstance());
+ @SuppressWarnings("deprecation")
+ HeaderFilter headerFilter = clazz.newInstance();
+ l.add(headerFilter);
} catch (ReflectiveOperationException e) {
throw new InternalError(e);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,70 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Represents one frame. May be initialized with a leftover buffer from previous
+ * frame. Call {@code haveFrame()} to determine if buffers contains at least one
+ * frame. If false, the obtain another buffer and call {@code}input(ByteBuffer)}.
+ * There may be additional bytes at end of the frame list.
+ */
+class FrameReader {
+
+ final List<ByteBuffer> buffers;
+
+ FrameReader() {
+ buffers = new LinkedList<>();
+ }
+
+ FrameReader(FrameReader that) {
+ this.buffers = that.buffers;
+ }
+
+ FrameReader(ByteBuffer remainder) {
+ buffers = new LinkedList<>();
+ if (remainder != null) {
+ buffers.add(remainder);
+ }
+ }
+
+ public synchronized void input(ByteBuffer buffer) {
+ buffers.add(buffer);
+ }
+
+ public synchronized boolean haveFrame() {
+ //buffers = Utils.superCompact(buffers, () -> ByteBuffer.allocate(Utils.BUFSIZE));
+ int size = 0;
+ for (ByteBuffer buffer : buffers) {
+ size += buffer.remaining();
+ }
+ if (size < 3) {
+ return false; // don't have length yet
+ }
+ // we at least have length field
+ int length = 0;
+ int j = 0;
+ ByteBuffer b = buffers.get(j);
+ b.mark();
+ for (int i=0; i<3; i++) {
+ while (!b.hasRemaining()) {
+ b.reset();
+ b = buffers.get(++j);
+ b.mark();
+ }
+ length = (length << 8) + (b.get() & 0xff);
+ }
+ b.reset();
+ return (size >= length + 9); // frame length
+ }
+
+ synchronized List<ByteBuffer> frame() {
+ return buffers;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,104 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class GoAwayFrame extends ErrorFrame {
+
+ GoAwayFrame() {
+ type = TYPE;
+ }
+
+ int lastStream;
+ byte[] debugData = new byte[0];
+
+ public static final int TYPE = 0x7;
+
+ // Flags
+ public static final int ACK = 0x1;
+
+ public void setDebugData(byte[] debugData) {
+ this.debugData = debugData;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " Debugdata: " + new String(debugData);
+ }
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case ACK:
+ return "ACK";
+ }
+ return super.flagAsString(flag);
+ }
+
+ public void setLastStream(int lastStream) {
+ this.lastStream = lastStream;
+ }
+
+ public int getLastStream() {
+ return this.lastStream;
+ }
+
+ public byte[] getDebugData() {
+ return debugData;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if (length < 8) {
+ throw new IOException("Invalid GoAway frame");
+ }
+ lastStream = bc.getInt() & 0x7fffffff;
+ errorCode = bc.getInt();
+ //debugData = bc.getBytes(8);
+ int datalen = length - 8;
+ if (datalen > 0) {
+ debugData = bc.getBytes(datalen);
+ Log.logError("GoAway debugData " + new String(debugData));
+ }
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(length);
+ buf.putInt(lastStream);
+ buf.putInt(errorCode);
+ if (length > 8) {
+ buf.put(debugData);
+ }
+ }
+
+ @Override
+ void computeLength() {
+ length = 8 + debugData.length;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Either a HeadersFrame or a ContinuationFrame
+ */
+abstract class HeaderFrame extends Http2Frame {
+
+ int offset;
+ int number;
+ int headerLength;
+ ByteBuffer[] headerBlocks;
+
+ public static final int END_HEADERS = 0x4;
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case END_HEADERS:
+ return "END_HEADERS";
+ }
+ return super.flagAsString(flag);
+ }
+
+ /**
+ * Sets the array of hpack encoded ByteBuffers
+ */
+ public void setHeaderBlock(ByteBuffer bufs[], int offset, int number) {
+ this.headerBlocks = bufs;
+ this.offset = offset;
+ this.number = number;
+ int length = 0;
+ for (int i=offset; i<offset+number; i++) {
+ length += headerBlocks[i].remaining();
+ }
+ this.headerLength = length;
+ }
+
+ public void setHeaderBlock(ByteBuffer bufs[]) {
+ setHeaderBlock(bufs, 0, bufs.length);
+ }
+
+ public ByteBuffer[] getHeaderBlock() {
+ return headerBlocks;
+ }
+
+ /**
+ * Returns true if this block is the final block of headers
+ */
+ public abstract boolean endHeaders();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeadersFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,138 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class HeadersFrame extends HeaderFrame {
+
+ public final static int TYPE = 0x1;
+
+ // Flags
+ public static final int END_STREAM = 0x1;
+ public static final int PADDED = 0x8;
+ public static final int PRIORITY = 0x20;
+
+
+ int padLength;
+ int streamDependency;
+ int weight;
+ boolean exclusive;
+
+ HeadersFrame() {
+ type = TYPE;
+ }
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case END_STREAM:
+ return "END_STREAM";
+ case PADDED:
+ return "PADDED";
+ case PRIORITY:
+ return "PRIORITY";
+ }
+ return super.flagAsString(flag);
+ }
+
+ public void setPadLength(int padLength) {
+ this.padLength = padLength;
+ flags |= PADDED;
+ }
+
+ public void setPriority(int streamDependency, boolean exclusive, int weight) {
+ this.streamDependency = streamDependency;
+ this.exclusive = exclusive;
+ this.weight = weight;
+ this.flags |= PRIORITY;
+ }
+
+ public int getStreamDependency() {
+ return streamDependency;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ @Override
+ public boolean endHeaders() {
+ return getFlag(END_HEADERS);
+ }
+
+ public boolean getExclusive() {
+ return exclusive;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if ((flags & PADDED) != 0) {
+ padLength = bc.getByte();
+ }
+ if ((flags & PRIORITY) != 0) {
+ int x = bc.getInt();
+ exclusive = (x & 0x80000000) != 0;
+ streamDependency = x & 0x7fffffff;
+ weight = bc.getByte();
+ }
+ headerLength = length - padLength;
+ headerBlocks = bc.getBuffers(headerLength);
+ }
+
+ @Override
+ void computeLength() {
+ int len = 0;
+ if ((flags & PADDED) != 0) {
+ len += (1 + padLength);
+ }
+ if ((flags & PRIORITY) != 0) {
+ len += 5;
+ }
+ len += headerLength;
+ this.length = len;
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(6);
+ if ((flags & PADDED) != 0) {
+ buf.put((byte)padLength);
+ }
+ if ((flags & PRIORITY) != 0) {
+ int x = exclusive ? 1 << 31 + streamDependency : streamDependency;
+ buf.putInt(x);
+ buf.put((byte)weight);
+ }
+ for (int i=0; i<headerBlocks.length; i++) {
+ bg.addByteBuffer(headerBlocks[i]);
+ }
+ if ((flags & PADDED) != 0) {
+ bg.addPadding(padLength);
+ }
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java Fri May 06 06:23:30 2016 -0700
@@ -64,32 +64,12 @@
if (connection != null) {
this.connection = connection;
} else {
- InetSocketAddress addr = getAddress(request);
+ InetSocketAddress addr = Utils.getAddress(request);
this.connection = HttpConnection.getConnection(addr, request);
}
this.requestAction = new Http1Request(request, this.connection);
}
- private static InetSocketAddress getAddress(HttpRequestImpl req) {
- URI uri = req.uri();
- if (uri == null) {
- return req.authority();
- }
- int port = uri.getPort();
- if (port == -1) {
- if (uri.getScheme().equalsIgnoreCase("https")) {
- port = 443;
- } else {
- port = 80;
- }
- }
- String host = uri.getHost();
- if (req.proxy() == null) {
- return new InetSocketAddress(host, port);
- } else {
- return InetSocketAddress.createUnresolved(host, port);
- }
- }
HttpConnection connection() {
return connection;
@@ -211,7 +191,7 @@
connection.close();
}
},
- () -> request.getAccessControlContext());
+ request::getAccessControlContext);
operations.add(cf);
return cf;
}
@@ -269,7 +249,7 @@
cf.completeExceptionally(e);
connection.close();
}
- }, () -> request.getAccessControlContext());
+ }, request::getAccessControlContext);
operations.add(cf);
return cf;
}
@@ -302,7 +282,7 @@
cf.completeExceptionally(e);
connection.close();
}
- }, () -> request.getAccessControlContext());
+ }, request::getAccessControlContext);
operations.add(cf);
return cf;
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java Fri May 06 06:23:30 2016 -0700
@@ -30,6 +30,7 @@
import java.util.Map;
import java.util.Set;
import java.net.InetSocketAddress;
+import java.net.http.HttpConnection.Mode;
import java.nio.charset.StandardCharsets;
import java.util.function.LongConsumer;
import static java.nio.charset.StandardCharsets.US_ASCII;
@@ -48,7 +49,8 @@
// See line 206 and below for description
final ByteBuffer[] buffers;
final HttpRequest.BodyProcessor requestProc;
- final HttpHeadersImpl userHeaders, systemHeaders;
+ final HttpHeaders userHeaders;
+ final HttpHeadersImpl systemHeaders;
final LongConsumer flowController;
boolean streaming;
long contentLength;
@@ -91,10 +93,10 @@
private void collectHeaders1(StringBuilder sb,
HttpRequestImpl request,
- HttpHeadersImpl headers)
+ HttpHeaders headers)
throws IOException
{
- Map<String,List<String>> h = headers.directMap();
+ Map<String,List<String>> h = headers.map();
Set<Map.Entry<String,List<String>>> entries = h.entrySet();
for (Map.Entry<String,List<String>> entry : entries) {
@@ -112,8 +114,6 @@
}
}
- private static final int BUFSIZE = 64 * 1024; // TODO: configurable?
-
private String getPathAndQuery(URI uri) {
String path = uri.getPath();
String query = uri.getQuery();
@@ -134,6 +134,25 @@
return addr.getHostString() + ":" + addr.getPort();
}
+ private String hostString() {
+ URI uri = request.uri();
+ int port = uri.getPort();
+ String host = uri.getHost();
+
+ boolean defaultPort;
+ if (port == -1)
+ defaultPort = true;
+ else if (request.secure())
+ defaultPort = port == 443;
+ else
+ defaultPort = port == 80;
+
+ if (defaultPort)
+ return host;
+ else
+ return host + ":" + Integer.toString(port);
+ }
+
private String requestURI() {
URI uri = request.uri();
String method = request.method();
@@ -161,6 +180,7 @@
void sendRequest() throws IOException {
collectHeaders();
+ chan.configureMode(Mode.BLOCKING);
if (contentLength == 0) {
chan.write(buffers, 0, 2);
} else if (contentLength > 0) {
@@ -196,7 +216,7 @@
buffers[0] = ByteBuffer.wrap(cmd.getBytes(StandardCharsets.US_ASCII));
URI uri = request.uri();
if (uri != null) {
- systemHeaders.setHeader("Host", uri.getHost());
+ systemHeaders.setHeader("Host", hostString());
}
if (request == null) {
// this is not a user request. No content
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java Fri May 06 06:23:30 2016 -0700
@@ -24,7 +24,6 @@
package java.net.http;
import java.io.IOException;
-import java.net.URI;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -23,11 +23,133 @@
*/
package java.net.http;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import static java.net.http.SettingsFrame.INITIAL_WINDOW_SIZE;
+import static java.net.http.SettingsFrame.ENABLE_PUSH;
+import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE;
+import static java.net.http.SettingsFrame.MAX_CONCURRENT_STREAMS;
+import static java.net.http.SettingsFrame.MAX_FRAME_SIZE;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Http2 specific aspects of HttpClientImpl
+ */
class Http2ClientImpl {
- Http2ClientImpl(HttpClientImpl t) {}
- String getSettingsString() {return "";}
- void debugPrint() {}
- Http2Connection getConnectionFor(HttpRequestImpl r) {
- return null;
+
+ final private HttpClientImpl client;
+
+ Http2ClientImpl(HttpClientImpl client) {
+ this.client = client;
+ }
+
+ /* Map key is "scheme:host:port" */
+ final private Map<String,Http2Connection> connections =
+ Collections.synchronizedMap(new HashMap<>());
+
+ final private Set<String> opening = Collections.synchronizedSet(new HashSet<>());
+
+ synchronized boolean haveConnectionFor(URI uri, InetSocketAddress proxy) {
+ return connections.containsKey(Http2Connection.keyFor(uri,proxy));
+ }
+
+ /**
+ * If a https request then blocks and waits until a connection is opened.
+ * Returns null if the request is 'http' as a different (upgrade)
+ * mechanism is used.
+ *
+ * Only one connection per destination is created. Blocks when opening
+ * connection, or when waiting for connection to be opened.
+ * First thread opens the connection and notifies the others when done.
+ *
+ * If the request is secure (https) then we open the connection here.
+ * If not, then the more complicated upgrade from 1.1 to 2 happens (not here)
+ * In latter case, when the Http2Connection is connected, putConnection() must
+ * be called to store it.
+ */
+ Http2Connection getConnectionFor(HttpRequestImpl req)
+ throws IOException, InterruptedException {
+ URI uri = req.uri();
+ InetSocketAddress proxy = req.proxy();
+ String key = Http2Connection.keyFor(uri, proxy);
+ Http2Connection connection;
+ synchronized (opening) {
+ while ((connection = connections.get(key)) == null) {
+ if (!req.secure()) {
+ return null;
+ }
+ if (!opening.contains(key)) {
+ opening.add(key);
+ break;
+ } else {
+ opening.wait();
+ }
+ }
+ }
+ if (connection != null) {
+ return connection;
+ }
+ // we are opening the connection here blocking until it is done.
+ connection = new Http2Connection(req);
+ synchronized (opening) {
+ connections.put(key, connection);
+ opening.remove(key);
+ opening.notifyAll();
+ }
+ return connection;
+ }
+
+
+ /*
+ * TODO: If there isn't a connection to the same destination, then
+ * store it. If there is already a connection, then close it
+ */
+ synchronized void putConnection(Http2Connection c) {
+ String key = c.key();
+ connections.put(key, c);
+ }
+
+ synchronized void deleteConnection(Http2Connection c) {
+ String key = c.key();
+ connections.remove(key);
+ }
+
+ HttpClientImpl client() {
+ return client;
+ }
+
+ /** Returns the client settings as a base64 (url) encoded string */
+ String getSettingsString() {
+ SettingsFrame sf = getClientSettings();
+ ByteBufferGenerator bg = new ByteBufferGenerator(client);
+ sf.writeOutgoing(bg);
+ byte[] settings = bg.asByteArray(9); // without the header
+ Base64.Encoder encoder = Base64.getUrlEncoder()
+ .withoutPadding();
+ return encoder.encodeToString(settings);
+ }
+
+ private static final int K = 1024;
+
+ SettingsFrame getClientSettings() {
+ SettingsFrame frame = new SettingsFrame();
+ frame.setParameter(HEADER_TABLE_SIZE, Utils.getIntegerNetProperty(
+ "java.net.httpclient.hpack.maxheadertablesize", 16 * K));
+ frame.setParameter(ENABLE_PUSH, Utils.getIntegerNetProperty(
+ "java.net.httpclient.enablepush", 1));
+ frame.setParameter(MAX_CONCURRENT_STREAMS, Utils.getIntegerNetProperty(
+ "java.net.httpclient.maxstreams", 16));
+ frame.setParameter(INITIAL_WINDOW_SIZE, Utils.getIntegerNetProperty(
+ "java.net.httpclient.windowsize", 32 * K));
+ frame.setParameter(MAX_FRAME_SIZE, Utils.getIntegerNetProperty(
+ "java.net.httpclient.maxframesize", 16 * K));
+ frame.computeLength();
+ return frame;
}
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -24,42 +24,767 @@
package java.net.http;
import java.io.IOException;
-import java.net.Authenticator;
-import java.net.CookieManager;
-import java.net.ProxySelector;
+import java.net.InetSocketAddress;
import java.net.URI;
-import static java.net.http.Utils.BUFSIZE;
+import java.net.http.HttpConnection.Mode;
import java.nio.ByteBuffer;
-import java.nio.channels.SelectableChannel;
-import java.nio.channels.SelectionKey;
-import static java.nio.channels.SelectionKey.OP_CONNECT;
-import static java.nio.channels.SelectionKey.OP_READ;
-import static java.nio.channels.SelectionKey.OP_WRITE;
-import java.nio.channels.Selector;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
-import java.util.concurrent.*;
-import java.security.NoSuchAlgorithmException;
-import java.util.ListIterator;
-import java.util.Optional;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import sun.net.httpclient.hpack.Encoder;
+import sun.net.httpclient.hpack.Decoder;
+import static java.net.http.SettingsFrame.*;
+import static java.net.http.Utils.BUFSIZE;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.stream.Collectors;
+import sun.net.httpclient.hpack.DecodingCallback;
+
+/**
+ * An Http2Connection. Encapsulates the socket(channel) and any SSLEngine used
+ * over it. Contains an HttpConnection which hides the SocketChannel SSL stuff.
+ *
+ * Http2Connections belong to a Http2ClientImpl, (one of) which belongs
+ * to a HttpClientImpl.
+ *
+ * Creation cases:
+ * 1) upgraded HTTP/1.1 plain tcp connection
+ * 2) prior knowledge directly created plain tcp connection
+ * 3) directly created HTTP/2 SSL connection which uses ALPN.
+ *
+ * Sending is done by writing directly to underlying HttpConnection object which
+ * is operating in async mode. No flow control applies on output at this level
+ * and all writes are just executed as puts to an output Q belonging to HttpConnection
+ * Flow control is implemented by HTTP/2 protocol itself.
+ *
+ * Hpack header compression
+ * and outgoing stream creation is also done here, because these operations
+ * must be synchronized at the socket level. Stream objects send frames simply
+ * by placing them on the connection's output Queue. sendFrame() is called
+ * from a higher level (Stream) thread.
+ *
+ * asyncReceive(ByteBuffer) is always called from the selector thread. It assembles
+ * incoming Http2Frames, and directs them to the appropriate Stream.incoming()
+ * or handles them directly itself. This thread performs hpack decompression
+ * and incoming stream creation (Server push). Incoming frames destined for a
+ * stream are provided by calling Stream.incoming().
+ */
+class Http2Connection implements BufferHandler {
+
+ final Queue<Http2Frame> outputQ;
+ volatile boolean closed;
+
+ //-------------------------------------
+ final HttpConnection connection;
+ HttpClientImpl client;
+ final Http2ClientImpl client2;
+ Map<Integer,Stream> streams;
+ int nextstreamid = 3; // stream 1 is registered separately
+ int nextPushStream = 2;
+ Encoder hpackOut;
+ Decoder hpackIn;
+ SettingsFrame clientSettings, serverSettings;
+ ByteBufferConsumer bbc;
+ final LinkedList<ByteBuffer> freeList;
+ final String key; // for HttpClientImpl.connections map
+ FrameReader reader;
+
+ // Connection level flow control windows
+ int sendWindow = INITIAL_WINDOW_SIZE;
+
+ final static int DEFAULT_FRAME_SIZE = 16 * 1024;
+ private static ByteBuffer[] empty = Utils.EMPTY_BB_ARRAY;
+
+ final ExecutorWrapper executor;
+
+ /**
+ * This is established by the protocol spec and the peer will update it with
+ * WINDOW_UPDATEs, which affects the sendWindow.
+ */
+ final static int INITIAL_WINDOW_SIZE = 64 * 1024 - 1;
+
+ // TODO: need list of control frames from other threads
+ // that need to be sent
+
+ /**
+ * Case 1) Create from upgraded HTTP/1.1 connection.
+ * Is ready to use. Will not be SSL. exchange is the Exchange
+ * that initiated the connection, whose response will be delivered
+ * on a Stream.
+ */
+ Http2Connection(HttpConnection connection, Http2ClientImpl client2,
+ Exchange exchange) throws IOException, InterruptedException {
+ this.outputQ = new Queue<>();
+ String msg = "Connection send window size " + Integer.toString(sendWindow);
+ Log.logTrace(msg);
+
+ //this.initialExchange = exchange;
+ assert !(connection instanceof SSLConnection);
+ this.connection = connection;
+ this.client = client2.client();
+ this.client2 = client2;
+ this.executor = client.executorWrapper();
+ this.freeList = new LinkedList<>();
+ this.key = keyFor(connection);
+ streams = Collections.synchronizedMap(new HashMap<>());
+ initCommon();
+ //sendConnectionPreface();
+ Stream initialStream = createStream(exchange);
+ initialStream.registerStream(1);
+ initialStream.requestSent();
+ sendConnectionPreface();
+ connection.configureMode(Mode.ASYNC);
+ // start reading and writing
+ // start reading
+ AsyncConnection asyncConn = (AsyncConnection)connection;
+ asyncConn.setAsyncCallbacks(this::asyncReceive, this::shutdown);
+ asyncReceive(connection.getRemaining());
+ asyncConn.startReading();
+ }
+
+ // async style but completes immediately
+ static CompletableFuture<Http2Connection> createAsync(HttpConnection connection,
+ Http2ClientImpl client2, Exchange exchange) {
+ CompletableFuture<Http2Connection> cf = new CompletableFuture<>();
+ try {
+ Http2Connection c = new Http2Connection(connection, client2, exchange);
+ cf.complete(c);
+ } catch (IOException | InterruptedException e) {
+ cf.completeExceptionally(e);
+ }
+ return cf;
+ }
+
+ /**
+ * Cases 2) 3)
+ *
+ * request is request to be sent.
+ */
+ Http2Connection(HttpRequestImpl request) throws IOException, InterruptedException {
+ InetSocketAddress proxy = request.proxy();
+ URI uri = request.uri();
+ InetSocketAddress addr = Utils.getAddress(request);
+ String msg = "Connection send window size " + Integer.toString(sendWindow);
+ Log.logTrace(msg);
+ this.key = keyFor(uri, proxy);
+ this.connection = HttpConnection.getConnection(addr, request, this);
+ streams = Collections.synchronizedMap(new HashMap<>());
+ this.client = request.client();
+ this.client2 = client.client2();
+ this.executor = client.executorWrapper();
+ this.freeList = new LinkedList<>();
+ this.outputQ = new Queue<>();
+ nextstreamid = 1;
+ initCommon();
+ connection.connect();
+ connection.configureMode(Mode.ASYNC);
+ // start reading
+ AsyncConnection asyncConn = (AsyncConnection)connection;
+ asyncConn.setAsyncCallbacks(this::asyncReceive, this::shutdown);
+ sendConnectionPreface();
+ asyncConn.startReading();
+ }
+
+ // NEW
+ synchronized void obtainSendWindow(int amount) throws InterruptedException {
+ while (amount > 0) {
+ int n = Math.min(amount, sendWindow);
+ sendWindow -= n;
+ amount -= n;
+ if (amount > 0)
+ wait();
+ }
+ }
+
+ synchronized void updateSendWindow(int amount) {
+ if (sendWindow == 0) {
+ sendWindow += amount;
+ notifyAll();
+ } else
+ sendWindow += amount;
+ }
+
+ synchronized int sendWindow() {
+ return sendWindow;
+ }
+
+ static String keyFor(HttpConnection connection) {
+ boolean isProxy = connection.isProxied();
+ boolean isSecure = connection.isSecure();
+ InetSocketAddress addr = connection.address();
+
+ return keyString(isSecure, isProxy, addr.getHostString(), addr.getPort());
+ }
+
+ static String keyFor(URI uri, InetSocketAddress proxy) {
+ boolean isSecure = uri.getScheme().equalsIgnoreCase("https");
+ boolean isProxy = proxy != null;
+
+ String host;
+ int port;
+
+ if (isProxy) {
+ host = proxy.getHostString();
+ port = proxy.getPort();
+ } else {
+ host = uri.getHost();
+ port = uri.getPort();
+ }
+ return keyString(isSecure, isProxy, host, port);
+ }
+
+ // {C,S}:{H:P}:host:port
+ // C indicates clear text connection "http"
+ // S indicates secure "https"
+ // H indicates host (direct) connection
+ // P indicates proxy
+ // Eg: "S:H:foo.com:80"
+ static String keyString(boolean secure, boolean proxy, String host, int port) {
+ char c1 = secure ? 'S' : 'C';
+ char c2 = proxy ? 'P' : 'H';
+
+ StringBuilder sb = new StringBuilder(128);
+ sb.append(c1).append(':').append(c2).append(':')
+ .append(host).append(':').append(port);
+ return sb.toString();
+ }
+
+ String key() {
+ return this.key;
+ }
+
+ void putConnection() {
+ client2.putConnection(this);
+ }
+
+ private static String toHexdump1(ByteBuffer bb) {
+ bb.mark();
+ StringBuilder sb = new StringBuilder(512);
+ Formatter f = new Formatter(sb);
+
+ while (bb.hasRemaining()) {
+ int i = Byte.toUnsignedInt(bb.get());
+ f.format("%02x:", i);
+ }
+ sb.deleteCharAt(sb.length()-1);
+ bb.reset();
+ return sb.toString();
+ }
+
+ private static String toHexdump(ByteBuffer bb) {
+ List<String> words = new ArrayList<>();
+ int i = 0;
+ bb.mark();
+ while (bb.hasRemaining()) {
+ if (i % 2 == 0) {
+ words.add("");
+ }
+ byte b = bb.get();
+ String hex = Integer.toHexString(256 + Byte.toUnsignedInt(b)).substring(1);
+ words.set(i / 2, words.get(i / 2) + hex);
+ i++;
+ }
+ bb.reset();
+ return words.stream().collect(Collectors.joining(" "));
+ }
+
+ private void decodeHeaders(HeaderFrame frame, DecodingCallback decoder) {
+ boolean endOfHeaders = frame.getFlag(HeaderFrame.END_HEADERS);
+
+ ByteBuffer[] buffers = frame.getHeaderBlock();
+ for (int i = 0; i < buffers.length; i++) {
+ hpackIn.decode(buffers[i], endOfHeaders, decoder);
+ }
+ }
+
+ int getInitialSendWindowSize() {
+ return serverSettings.getParameter(SettingsFrame.INITIAL_WINDOW_SIZE);
+ }
+
+ void close() {
+ GoAwayFrame f = new GoAwayFrame();
+ f.setDebugData("Requested by user".getBytes());
+ // TODO: set last stream. For now zero ok.
+ sendFrame(f);
+ }
+
+ // BufferHandler methods
+
+ @Override
+ public ByteBuffer getBuffer(int n) {
+ return client.getBuffer(n);
+ }
+
+ @Override
+ public void returnBuffer(ByteBuffer buf) {
+ client.returnBuffer(buf);
+ }
-class Http2Connection {
- static CompletableFuture<Http2Connection> createAsync(
- HttpConnection connection, Http2ClientImpl client2, Exchange exchange) {
- return null;
+ @Override
+ public void setMinBufferSize(int n) {
+ client.setMinBufferSize(n);
+ }
+
+ private final Object readlock = new Object();
+
+ void asyncReceive(ByteBuffer buffer) {
+ synchronized (readlock) {
+ try {
+ if (reader == null) {
+ reader = new FrameReader(buffer);
+ } else {
+ reader.input(buffer);
+ }
+ while (true) {
+ if (reader.haveFrame()) {
+ List<ByteBuffer> buffers = reader.frame();
+
+ ByteBufferConsumer bbc = new ByteBufferConsumer(buffers, this::getBuffer);
+ processFrame(bbc);
+ if (bbc.consumed()) {
+ reader = new FrameReader();
+ return;
+ } else {
+ reader = new FrameReader(reader);
+ }
+ } else
+ return;
+ }
+ } catch (Throwable e) {
+ String msg = Utils.stackTrace(e);
+ Log.logTrace(msg);
+ shutdown(e);
+ }
+ }
+ }
+
+ void shutdown(Throwable t) {
+ System.err.println("Shutdown: " + t);
+ t.printStackTrace();
+ closed = true;
+ client2.deleteConnection(this);
+ Collection<Stream> c = streams.values();
+ for (Stream s : c) {
+ s.cancelImpl(t);
+ }
+ connection.close();
+ }
+
+ /**
+ * Handles stream 0 (common) frames that apply to whole connection and passes
+ * other stream specific frames to that Stream object.
+ *
+ * Invokes Stream.incoming() which is expected to process frame without
+ * blocking.
+ */
+ void processFrame(ByteBufferConsumer bbc) throws IOException, InterruptedException {
+ Http2Frame frame = Http2Frame.readIncoming(bbc);
+ Log.logFrames(frame, "IN");
+ int streamid = frame.streamid();
+ if (streamid == 0) {
+ handleCommonFrame(frame);
+ } else {
+ Stream stream = getStream(streamid);
+ if (stream == null) {
+ // should never receive a frame with unknown stream id
+ resetStream(streamid, ResetFrame.PROTOCOL_ERROR);
+ }
+ if (frame instanceof PushPromiseFrame) {
+ PushPromiseFrame pp = (PushPromiseFrame)frame;
+ handlePushPromise(stream, pp);
+ } else if (frame instanceof HeaderFrame) {
+ // decode headers (or continuation)
+ decodeHeaders((HeaderFrame) frame, stream.rspHeadersConsumer());
+ stream.incoming(frame);
+ } else
+ stream.incoming(frame);
+ }
+ }
+
+ private void handlePushPromise(Stream parent, PushPromiseFrame pp)
+ throws IOException, InterruptedException {
+
+ HttpRequestImpl parentReq = parent.request;
+ int promisedStreamid = pp.getPromisedStream();
+ if (promisedStreamid != nextPushStream) {
+ resetStream(promisedStreamid, ResetFrame.PROTOCOL_ERROR);
+ return;
+ } else {
+ nextPushStream += 2;
+ }
+ HeaderDecoder decoder = new HeaderDecoder();
+ decodeHeaders(pp, decoder);
+ HttpHeadersImpl headers = decoder.headers();
+ HttpRequestImpl pushReq = HttpRequestImpl.createPushRequest(parentReq, headers);
+
+ Stream.PushedStream pushStream = createPushStream(parent, pushReq);
+ pushStream.registerStream(promisedStreamid);
+ parent.incoming_pushPromise(pushReq, pushStream);
+ }
+
+ private void handleCommonFrame(Http2Frame frame)
+ throws IOException, InterruptedException {
+
+ switch (frame.type()) {
+ case SettingsFrame.TYPE:
+ { SettingsFrame f = (SettingsFrame)frame;
+ handleSettings(f);}
+ break;
+ case PingFrame.TYPE:
+ { PingFrame f = (PingFrame)frame;
+ handlePing(f);}
+ break;
+ case GoAwayFrame.TYPE:
+ { GoAwayFrame f = (GoAwayFrame)frame;
+ handleGoAway(f);}
+ break;
+ case WindowUpdateFrame.TYPE:
+ { WindowUpdateFrame f = (WindowUpdateFrame)frame;
+ handleWindowUpdate(f);}
+ break;
+ default:
+ protocolError(ErrorFrame.PROTOCOL_ERROR);
+ }
+ }
+
+ void resetStream(int streamid, int code) throws IOException, InterruptedException {
+ Log.logError(
+ "Resetting stream {0,number,integer} with error code {1,number,integer}",
+ streamid, code);
+ ResetFrame frame = new ResetFrame();
+ frame.streamid(streamid);
+ frame.setErrorCode(code);
+ sendFrame(frame);
+ streams.remove(streamid);
+ }
+
+ private void handleWindowUpdate(WindowUpdateFrame f)
+ throws IOException, InterruptedException {
+ updateSendWindow(f.getUpdate());
+ }
+
+ private void protocolError(int errorCode)
+ throws IOException, InterruptedException {
+ GoAwayFrame frame = new GoAwayFrame();
+ frame.setErrorCode(errorCode);
+ sendFrame(frame);
+ String msg = "Error code: " + errorCode;
+ shutdown(new IOException("protocol error"));
+ }
+
+ private void handleSettings(SettingsFrame frame)
+ throws IOException, InterruptedException {
+ if (frame.getFlag(SettingsFrame.ACK)) {
+ // ignore ack frames for now.
+ return;
+ }
+ serverSettings = frame;
+ SettingsFrame ack = getAckFrame(frame.streamid());
+ sendFrame(ack);
+ }
+
+ private void handlePing(PingFrame frame)
+ throws IOException, InterruptedException {
+ frame.setFlag(PingFrame.ACK);
+ sendFrame(frame);
+ }
+
+ private void handleGoAway(GoAwayFrame frame)
+ throws IOException, InterruptedException {
+ //System.err.printf("GoAWAY: %s\n", ErrorFrame.stringForCode(frame.getErrorCode()));
+ shutdown(new IOException("GOAWAY received"));
+ }
+
+ private void initCommon() {
+ clientSettings = client2.getClientSettings();
+
+ // serverSettings will be updated by server
+ serverSettings = SettingsFrame.getDefaultSettings();
+ hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE));
+ hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
+ }
+
+ /**
+ * Max frame size we are allowed to send
+ */
+ public int getMaxSendFrameSize() {
+ int param = serverSettings.getParameter(MAX_FRAME_SIZE);
+ if (param == -1) {
+ param = DEFAULT_FRAME_SIZE;
+ }
+ return param;
+ }
+
+ /**
+ * Max frame size we will receive
+ */
+ public int getMaxReceiveFrameSize() {
+ return clientSettings.getParameter(MAX_FRAME_SIZE);
+ }
+
+ // Not sure how useful this is.
+ public int getMaxHeadersSize() {
+ return serverSettings.getParameter(MAX_HEADER_LIST_SIZE);
+ }
+
+ private static final String CLIENT_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
+
+ private static final byte[] PREFACE_BYTES =
+ CLIENT_PREFACE.getBytes(StandardCharsets.ISO_8859_1);
+
+ /**
+ * Sends Connection preface and Settings frame with current preferred
+ * values
+ */
+ private void sendConnectionPreface() throws IOException {
+ ByteBufferGenerator bg = new ByteBufferGenerator(this);
+ bg.getBuffer(PREFACE_BYTES.length).put(PREFACE_BYTES);
+ ByteBuffer[] ba = bg.getBufferArray();
+ connection.write(ba, 0, ba.length);
+
+ bg = new ByteBufferGenerator(this);
+ SettingsFrame sf = client2.getClientSettings();
+ Log.logFrames(sf, "OUT");
+ sf.writeOutgoing(bg);
+ WindowUpdateFrame wup = new WindowUpdateFrame();
+ wup.streamid(0);
+ // send a Window update for the receive buffer we are using
+ // minus the initial 64 K specified in protocol
+ wup.setUpdate(client2.client().getReceiveBufferSize() - (64 * 1024 - 1));
+ wup.computeLength();
+ wup.writeOutgoing(bg);
+ Log.logFrames(wup, "OUT");
+ ba = bg.getBufferArray();
+ connection.write(ba, 0, ba.length);
+ }
+
+ /**
+ * Returns an existing Stream with given id, or null if doesn't exist
+ */
+ Stream getStream(int streamid) {
+ return streams.get(streamid);
+ }
+
+ /**
+ * Creates Stream with given id.
+ */
+ Stream createStream(Exchange exchange) {
+ Stream stream = new Stream(client, this, exchange);
+ return stream;
+ }
+
+ Stream.PushedStream createPushStream(Stream parent, HttpRequestImpl pushReq) {
+ Stream.PushGroup<?> pg = parent.request.pushGroup();
+ return new Stream.PushedStream(pg, client, this, parent, pushReq);
+ }
+
+ void putStream(Stream stream, int streamid) {
+ streams.put(streamid, stream);
+ }
+
+ void deleteStream(Stream stream) {
+ streams.remove(stream.streamid);
+ }
+
+ static final int MAX_STREAM = Integer.MAX_VALUE - 2;
+
+ // Number of header bytes in a Headers Frame
+ final static int HEADERS_HEADER_SIZE = 15;
+
+ // Number of header bytes in a Continuation frame
+ final static int CONTIN_HEADER_SIZE = 9;
+
+ /**
+ * Encode the headers into a List<ByteBuffer> and then create HEADERS
+ * and CONTINUATION frames from the list and return the List<Http2Frame>.
+ *
+ * @param frame
+ * @return
+ */
+ private LinkedList<Http2Frame> encodeHeaders(OutgoingHeaders frame) {
+ LinkedList<ByteBuffer> buffers = new LinkedList<>();
+ ByteBuffer buf = getBuffer();
+ buffers.add(buf);
+ encodeHeadersImpl(frame.stream.getRequestPseudoHeaders(), buffers);
+ encodeHeadersImpl(frame.getUserHeaders(), buffers);
+ encodeHeadersImpl(frame.getSystemHeaders(), buffers);
+
+ for (ByteBuffer b : buffers) {
+ b.flip();
}
- Http2Connection(HttpConnection connection, Http2ClientImpl client2,
- Exchange exchange) throws IOException, InterruptedException {
+ LinkedList<Http2Frame> frames = new LinkedList<>();
+ int maxframesize = getMaxSendFrameSize();
+
+ HeadersFrame oframe = new HeadersFrame();
+ oframe.setFlags(frame.getFlags());
+ oframe.streamid(frame.streamid());
+
+ oframe.setHeaderBlock(getBufferArray(buffers, maxframesize));
+ frames.add(oframe);
+ // Any buffers left?
+ boolean done = buffers.isEmpty();
+ if (done) {
+ oframe.setFlag(HeaderFrame.END_HEADERS);
+ } else {
+ ContinuationFrame cf = null;
+ while (!done) {
+ cf = new ContinuationFrame();
+ cf.streamid(frame.streamid());
+ cf.setHeaderBlock(getBufferArray(buffers, maxframesize));
+ frames.add(cf);
+ done = buffers.isEmpty();
+ }
+ cf.setFlag(HeaderFrame.END_HEADERS);
+ }
+ return frames;
+ }
+
+ // should always return at least one buffer
+ private static ByteBuffer[] getBufferArray(LinkedList<ByteBuffer> list, int maxsize) {
+ assert maxsize >= BUFSIZE;
+ LinkedList<ByteBuffer> newlist = new LinkedList<>();
+ int size = list.size();
+ int nbytes = 0;
+ for (int i=0; i<size; i++) {
+ ByteBuffer buf = list.getFirst();
+ if (nbytes + buf.remaining() <= maxsize) {
+ nbytes += buf.remaining();
+ newlist.add(buf);
+ list.remove();
+ } else {
+ break;
+ }
+ }
+ return newlist.toArray(empty);
+ }
+
+ /**
+ * Encode all the headers from the given HttpHeadersImpl into the given List.
+ */
+ private void encodeHeadersImpl(HttpHeaders hdrs, LinkedList<ByteBuffer> buffers) {
+ ByteBuffer buffer;
+ if (!(buffer = buffers.getLast()).hasRemaining()) {
+ buffer = getBuffer();
+ buffers.add(buffer);
+ }
+ for (Map.Entry<String, List<String>> e : hdrs.map().entrySet()) {
+ String key = e.getKey();
+ String lkey = key.toLowerCase();
+ List<String> values = e.getValue();
+ for (String value : values) {
+ hpackOut.header(lkey, value);
+ boolean encoded = false;
+ do {
+ encoded = hpackOut.encode(buffer);
+ if (!encoded) {
+ buffer = getBuffer();
+ buffers.add(buffer);
+ }
+ } while (!encoded);
+ }
+ }
+ }
+
+ public void sendFrames(List<Http2Frame> frames) throws IOException, InterruptedException {
+ for (Http2Frame frame : frames) {
+ sendFrame(frame);
+ }
}
- Stream getStream(int i) {return null;}
- Stream createStream(Exchange ex) {return null;}
- void putConnection() {}
+ static Throwable getExceptionFrom(CompletableFuture<?> cf) {
+ try {
+ cf.get();
+ return null;
+ } catch (Throwable e) {
+ if (e.getCause() != null)
+ return e.getCause();
+ else
+ return e;
+ }
+ }
+
+
+ void execute(Runnable r) {
+ executor.execute(r, null);
+ }
+
+ private final Object sendlock = new Object();
+
+ /**
+ *
+ */
+ void sendFrame(Http2Frame frame) {
+ synchronized (sendlock) {
+ try {
+ if (frame instanceof OutgoingHeaders) {
+ OutgoingHeaders oh = (OutgoingHeaders) frame;
+ Stream stream = oh.getStream();
+ stream.registerStream(nextstreamid);
+ oh.streamid(nextstreamid);
+ nextstreamid += 2;
+ // set outgoing window here. This allows thread sending
+ // body to proceed.
+ stream.updateOutgoingWindow(getInitialSendWindowSize());
+ LinkedList<Http2Frame> frames = encodeHeaders(oh);
+ for (Http2Frame f : frames) {
+ sendOneFrame(f);
+ }
+ } else {
+ sendOneFrame(frame);
+ }
+
+ } catch (IOException e) {
+ if (!closed) {
+ Log.logError(e);
+ shutdown(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Send a frame.
+ *
+ * @param frame
+ * @throws IOException
+ */
+ private void sendOneFrame(Http2Frame frame) throws IOException {
+ ByteBufferGenerator bbg = new ByteBufferGenerator(this);
+ frame.computeLength();
+ Log.logFrames(frame, "OUT");
+ frame.writeOutgoing(bbg);
+ ByteBuffer[] currentBufs = bbg.getBufferArray();
+ connection.write(currentBufs, 0, currentBufs.length);
+ }
+
+
+ private SettingsFrame getAckFrame(int streamid) {
+ SettingsFrame frame = new SettingsFrame();
+ frame.setFlag(SettingsFrame.ACK);
+ frame.streamid(streamid);
+ return frame;
+ }
+
+ static class HeaderDecoder implements DecodingCallback {
+ HttpHeadersImpl headers;
+
+ HeaderDecoder() {
+ this.headers = new HttpHeadersImpl();
+ }
+
+ @Override
+ public void onDecoded(CharSequence name, CharSequence value) {
+ headers.addHeader(name.toString(), value.toString());
+ }
+
+ HttpHeadersImpl headers() {
+ return headers;
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,211 @@
+/*
+ * 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
+ * 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
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * When sending a frame, the length field must be set in sub-class
+ * by calling computeLength()
+ */
+abstract class Http2Frame {
+
+ int length = -1;
+ int type;
+ int streamid;
+ int flags;
+
+ // called when reading in only
+ void initCommon(int length, int type, int streamid, int flags) {
+ this.length = length;
+ this.type = type;
+ this.streamid = streamid;
+ this.flags = flags;
+ }
+
+ public int length() {
+ return length;
+ }
+
+ public int type() {
+ return type;
+ }
+
+ public int streamid() {
+ return streamid;
+ }
+
+ public void setFlag(int flag) {
+ flags |= flag;
+ }
+
+ public void setFlags(int flags) {
+ this.flags = flags;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public boolean getFlag(int flag) {
+ return (flags & flag) != 0;
+ }
+
+ public void clearFlag(int flag) {
+ flags &= 0xffffffff ^ flag;
+ }
+
+ public void streamid(int streamid) {
+ this.streamid = streamid;
+ }
+
+ abstract void readIncomingImpl(ByteBufferConsumer bc) throws IOException;
+
+ /**
+ * assume given array contains at least one complete frame.
+ */
+ static Http2Frame readIncoming(ByteBufferConsumer bc) throws IOException {
+ int x = bc.getInt();
+ int length = x >> 8;
+ int type = x & 0xff;
+ int flags = bc.getByte();
+ int streamid = bc.getInt();
+ Http2Frame f = null;
+ switch (type) {
+ case DataFrame.TYPE:
+ f = new DataFrame();
+ break;
+ case HeadersFrame.TYPE:
+ f = new HeadersFrame();
+ break;
+ case ContinuationFrame.TYPE:
+ f = new ContinuationFrame();
+ break;
+ case ResetFrame.TYPE:
+ f = new ResetFrame();
+ break;
+ case PriorityFrame.TYPE:
+ f = new PriorityFrame();
+ break;
+ case SettingsFrame.TYPE:
+ f = new SettingsFrame();
+ break;
+ case GoAwayFrame.TYPE:
+ f = new GoAwayFrame();
+ break;
+ case PingFrame.TYPE:
+ f = new PingFrame();
+ break;
+ case PushPromiseFrame.TYPE:
+ f = new PushPromiseFrame();
+ break;
+ case WindowUpdateFrame.TYPE:
+ f = new WindowUpdateFrame();
+ break;
+ default:
+ String msg = Integer.toString(type);
+ throw new IOException("unknown frame type " + msg);
+ }
+ f.initCommon(length, type, streamid, flags);
+ f.readIncomingImpl(bc);
+ return f;
+ }
+
+ public String typeAsString() {
+ return asString(this.type);
+ }
+
+ public static String asString(int type) {
+ switch (type) {
+ case DataFrame.TYPE:
+ return "DATA";
+ case HeadersFrame.TYPE:
+ return "HEADERS";
+ case ContinuationFrame.TYPE:
+ return "CONTINUATION";
+ case ResetFrame.TYPE:
+ return "RESET";
+ case PriorityFrame.TYPE:
+ return "PRIORITY";
+ case SettingsFrame.TYPE:
+ return "SETTINGS";
+ case GoAwayFrame.TYPE:
+ return "GOAWAY";
+ case PingFrame.TYPE:
+ return "PING";
+ case PushPromiseFrame.TYPE:
+ return "PUSH_PROMISE";
+ case WindowUpdateFrame.TYPE:
+ return "WINDOW_UPDATE";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(typeAsString())
+ .append(": length=")
+ .append(Integer.toString(length))
+ .append(", streamid=")
+ .append(streamid)
+ .append(", flags=");
+
+ int f = flags;
+ int i = 0;
+ if (f == 0) {
+ sb.append("0 ");
+ } else {
+ while (f != 0) {
+ if ((f & 1) == 1) {
+ sb.append(flagAsString(1 << i))
+ .append(' ');
+ }
+ f = f >> 1;
+ i++;
+ }
+ }
+ return sb.toString();
+ }
+
+ // Override
+ String flagAsString(int f) {
+ return "unknown";
+ }
+
+ abstract void computeLength();
+
+ void writeOutgoing(ByteBufferGenerator bg) {
+ if (length == -1) {
+ throw new InternalError("Length not set on outgoing frame");
+ }
+ ByteBuffer buf = bg.getBuffer(9);
+ int x = (length << 8) + type;
+ buf.putInt(x);
+ buf.put((byte)flags);
+ buf.putInt(streamid);
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java Fri May 06 06:23:30 2016 -0700
@@ -23,28 +23,32 @@
*/
package java.net.http;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
import java.io.IOException;
import java.net.Authenticator;
import java.net.CookieManager;
import java.net.ProxySelector;
import java.net.URI;
-import static java.net.http.Utils.BUFSIZE;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
-import static java.nio.channels.SelectionKey.OP_CONNECT;
-import static java.nio.channels.SelectionKey.OP_READ;
-import static java.nio.channels.SelectionKey.OP_WRITE;
import java.nio.channels.Selector;
-import java.util.*;
-import java.util.stream.Stream;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
-import java.security.NoSuchAlgorithmException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
+import java.util.stream.Stream;
+
+import static java.net.http.Utils.BUFSIZE;
/**
* Client implementation. Contains all configuration information and also
@@ -53,6 +57,9 @@
*/
class HttpClientImpl extends HttpClient implements BufferHandler {
+ private static final ThreadFactory defaultFactory =
+ (r -> new Thread(null, r, "HttpClient_worker", 0, true));
+
private final CookieManager cookieManager;
private final Redirect followRedirects;
private final ProxySelector proxySelector;
@@ -67,7 +74,6 @@
private final SelectorManager selmgr;
private final FilterFactory filters;
private final Http2ClientImpl client2;
- private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
private final LinkedList<TimeoutEvent> timeouts;
public static HttpClientImpl create(HttpClientBuilderImpl builder) {
@@ -115,7 +121,6 @@
throw new InternalError(e);
}
selmgr.setDaemon(true);
- selmgr.setName("HttpSelector");
filters = new FilterFactory();
initFilters();
}
@@ -135,7 +140,7 @@
* 4) - mark connection as blocking
* 5) - call AsyncEvent.handle()
*
- * If exchange needs to block again, then call registerEvent() again
+ * If exchange needs to block again, then call registerEvent() again
*/
void registerEvent(AsyncEvent exchange) throws IOException {
selmgr.register(exchange);
@@ -145,35 +150,56 @@
return client2;
}
- LinkedList<ByteBuffer> freelist = new LinkedList<>();
+ /**
+ * We keep one size of buffer on free list. That size may increase
+ * depending on demand. If that happens we dispose of free buffers
+ * that are smaller than new size.
+ */
+ private final LinkedList<ByteBuffer> freelist = new LinkedList<>();
+ int currentSize = BUFSIZE;
@Override
- public synchronized ByteBuffer getBuffer() {
- if (freelist.isEmpty()) {
- return ByteBuffer.allocate(BUFSIZE);
+ public synchronized ByteBuffer getBuffer(int size) {
+
+ ByteBuffer buf;
+ if (size == -1)
+ size = currentSize;
+
+ if (size > currentSize)
+ currentSize = size;
+
+ while (!freelist.isEmpty()) {
+ buf = freelist.removeFirst();
+ if (buf.capacity() < currentSize)
+ continue;
+ buf.clear();
+ return buf;
}
- return freelist.removeFirst();
+ return ByteBuffer.allocate(size);
}
@Override
public synchronized void returnBuffer(ByteBuffer buffer) {
- buffer.clear();
freelist.add(buffer);
}
+ @Override
+ public synchronized void setMinBufferSize(int n) {
+ currentSize = Math.max(n, currentSize);
+ }
// Main loop for this client's selector
+ private final class SelectorManager extends Thread {
- class SelectorManager extends Thread {
- final Selector selector;
- boolean closed;
-
- final List<AsyncEvent> readyList;
- final List<AsyncEvent> registrations;
+ private final Selector selector;
+ private volatile boolean closed;
+ private final List<AsyncEvent> readyList;
+ private final List<AsyncEvent> registrations;
SelectorManager() throws IOException {
- readyList = new LinkedList<>();
- registrations = new LinkedList<>();
+ super(null, null, "SelectorManager", 0, false);
+ readyList = new ArrayList<>();
+ registrations = new ArrayList<>();
selector = Selector.open();
}
@@ -193,32 +219,13 @@
closed = true;
try {
selector.close();
- } catch (IOException e) {}
- }
-
- private List<AsyncEvent> copy(List<AsyncEvent> list) {
- LinkedList<AsyncEvent> c = new LinkedList<>();
- for (AsyncEvent e : list) {
- c.add(e);
- }
- return c;
- }
-
- String opvals(int i) {
- StringBuilder sb = new StringBuilder();
- if ((i & OP_READ) != 0)
- sb.append("OP_READ ");
- if ((i & OP_CONNECT) != 0)
- sb.append("OP_CONNECT ");
- if ((i & OP_WRITE) != 0)
- sb.append("OP_WRITE ");
- return sb.toString();
+ } catch (IOException ignored) { }
}
@Override
public void run() {
try {
- while (true) {
+ while (!Thread.currentThread().isInterrupted()) {
synchronized (this) {
for (AsyncEvent exchange : registrations) {
SelectableChannel c = exchange.channel();
@@ -229,7 +236,7 @@
if (key == null) {
sa = new SelectorAttachment(c, selector);
} else {
- sa = (SelectorAttachment)key.attachment();
+ sa = (SelectorAttachment) key.attachment();
}
sa.register(exchange);
} catch (IOException e) {
@@ -243,6 +250,7 @@
}
long timeval = getTimeoutValue();
long now = System.currentTimeMillis();
+ //debugPrint(selector);
int n = selector.select(timeval);
if (n == 0) {
signalTimeouts(now);
@@ -251,7 +259,7 @@
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
- SelectorAttachment sa = (SelectorAttachment)key.attachment();
+ SelectorAttachment sa = (SelectorAttachment) key.attachment();
int eventsOccurred = key.readyOps();
sa.events(eventsOccurred).forEach(readyList::add);
sa.resetInterestOps(eventsOccurred);
@@ -260,10 +268,8 @@
selector.selectedKeys().clear();
for (AsyncEvent exchange : readyList) {
- if (exchange instanceof AsyncEvent.Blocking) {
+ if (exchange.blocking()) {
exchange.channel().configureBlocking(true);
- } else {
- assert exchange instanceof AsyncEvent.NonBlocking;
}
executor.synchronize();
handleEvent(exchange); // will be delegated to executor
@@ -272,14 +278,26 @@
}
} catch (Throwable e) {
if (!closed) {
- System.err.println("HttpClientImpl terminating on error");
// This terminates thread. So, better just print stack trace
String err = Utils.stackTrace(e);
Log.logError("HttpClientImpl: fatal error: " + err);
}
+ } finally {
+ shutdown();
}
}
+ void debugPrint(Selector selector) {
+ System.err.println("Selector: debugprint start");
+ Set<SelectionKey> keys = selector.keys();
+ for (SelectionKey key : keys) {
+ SelectableChannel c = key.channel();
+ int ops = key.interestOps();
+ System.err.printf("selector chan:%s ops:%d\n", c, ops);
+ }
+ System.err.println("Selector: debugprint end");
+ }
+
void handleEvent(AsyncEvent e) {
if (closed) {
e.abort();
@@ -303,7 +321,7 @@
private final SelectableChannel chan;
private final Selector selector;
private final ArrayList<AsyncEvent> pending;
- private int interestops;
+ private int interestOps;
SelectorAttachment(SelectableChannel chan, Selector selector) {
this.pending = new ArrayList<>();
@@ -312,53 +330,53 @@
}
void register(AsyncEvent e) throws ClosedChannelException {
- int newops = e.interestOps();
- boolean reRegister = (interestops & newops) != newops;
- interestops |= newops;
+ int newOps = e.interestOps();
+ boolean reRegister = (interestOps & newOps) != newOps;
+ interestOps |= newOps;
pending.add(e);
if (reRegister) {
// first time registration happens here also
- chan.register(selector, interestops, this);
+ chan.register(selector, interestOps, this);
}
}
- int interestOps() {
- return interestops;
- }
-
/**
* Returns a Stream<AsyncEvents> containing only events that are
- * registered with the given {@code interestop}.
+ * registered with the given {@code interestOps}.
*/
- Stream<AsyncEvent> events(int interestop) {
+ Stream<AsyncEvent> events(int interestOps) {
return pending.stream()
- .filter(ev -> (ev.interestOps() & interestop) != 0);
+ .filter(ev -> (ev.interestOps() & interestOps) != 0);
}
/**
- * Removes any events with the given {@code interestop}, and if no
+ * Removes any events with the given {@code interestOps}, and if no
* events remaining, cancels the associated SelectionKey.
*/
- void resetInterestOps(int interestop) {
- int newops = 0;
+ void resetInterestOps(int interestOps) {
+ int newOps = 0;
Iterator<AsyncEvent> itr = pending.iterator();
while (itr.hasNext()) {
AsyncEvent event = itr.next();
int evops = event.interestOps();
- if ((evops & interestop) != 0) {
+ if (event.repeating()) {
+ newOps |= evops;
+ continue;
+ }
+ if ((evops & interestOps) != 0) {
itr.remove();
} else {
- newops |= evops;
+ newOps |= evops;
}
}
- interestops = newops;
+ this.interestOps = newOps;
SelectionKey key = chan.keyFor(selector);
- if (newops == 0) {
+ if (newOps == 0) {
key.cancel();
} else {
- key.interestOps(newops);
+ key.interestOps(newOps);
}
}
}
@@ -366,7 +384,8 @@
/**
* Creates a HttpRequest associated with this group.
*
- * @throws IllegalStateException if the group has been stopped
+ * @throws IllegalStateException
+ * if the group has been stopped
*/
@Override
public HttpRequestBuilderImpl request() {
@@ -376,7 +395,8 @@
/**
* Creates a HttpRequest associated with this group.
*
- * @throws IllegalStateException if the group has been stopped
+ * @throws IllegalStateException
+ * if the group has been stopped
*/
@Override
public HttpRequestBuilderImpl request(URI uri) {
@@ -444,16 +464,12 @@
return version.equals(Version.HTTP_2);
}
- //void setHttp2NotSupported(String host) {
- //http2NotSupported.put(host, false);
- //}
-
- final void initFilters() {
+ private void initFilters() {
addFilter(AuthenticationFilter.class);
addFilter(RedirectFilter.class);
}
- final void addFilter(Class<? extends HeaderFilter> f) {
+ private void addFilter(Class<? extends HeaderFilter> f) {
filters.addFilter(f);
}
@@ -479,14 +495,14 @@
iter.previous();
break;
} else if (!iter.hasNext()) {
- event.delta = event.timeval - listval ;
+ event.delta = event.timeval - listval;
}
}
iter.add(event);
selmgr.wakeupSelector();
}
- synchronized void signalTimeouts(long then) {
+ private synchronized void signalTimeouts(long then) {
if (timeouts.isEmpty()) {
return;
}
@@ -532,12 +548,12 @@
// used for the connection window
int getReceiveBufferSize() {
return Utils.getIntegerNetProperty(
- "sun.net.httpclient.connectionWindowSize", 256 * 1024
+ "java.net.httpclient.connectionWindowSize", 256 * 1024
);
}
// returns 0 meaning block forever, or a number of millis to block for
- synchronized long getTimeoutValue() {
+ private synchronized long getTimeoutValue() {
if (timeouts.isEmpty()) {
return 0;
} else {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java Fri May 06 06:23:30 2016 -0700
@@ -23,9 +23,8 @@
*/
package java.net.http;
-import java.io.FileOutputStream;
+import java.io.Closeable;
import java.io.IOException;
-import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
@@ -42,7 +41,17 @@
* SSLConnection: TLS channel direct to server
* SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel
*/
-abstract class HttpConnection implements BufferHandler {
+abstract class HttpConnection implements BufferHandler, Closeable {
+
+ protected final static ByteBuffer emptyBuf = Utils.EMPTY_BYTEBUFFER;
+
+ enum Mode {
+ BLOCKING,
+ NON_BLOCKING,
+ ASYNC
+ }
+
+ protected Mode mode;
// address we are connected to. Could be a server or a proxy
final InetSocketAddress address;
@@ -52,6 +61,7 @@
HttpConnection(InetSocketAddress address, HttpClientImpl client) {
this.address = address;
this.client = client;
+ this.buffer = emptyBuf;
}
/**
@@ -68,7 +78,21 @@
*/
public static HttpConnection getConnection(InetSocketAddress addr,
HttpRequestImpl request) {
- return getConnectionImpl(addr, request);
+ return getConnectionImpl(addr, request, null);
+ }
+
+ /**
+ * Called specifically to get an async connection for HTTP/2 over SSL.
+ *
+ * @param addr
+ * @param request
+ * @param http2
+ * @return
+ */
+ public static HttpConnection getConnection(InetSocketAddress addr,
+ HttpRequestImpl request, Http2Connection http2) {
+
+ return getConnectionImpl(addr, request, http2);
}
public abstract void connect() throws IOException, InterruptedException;
@@ -93,7 +117,7 @@
// at beginning of response.
ByteBuffer getRemaining() {
ByteBuffer b = buffer;
- buffer = null;
+ buffer = emptyBuf;
return b;
}
@@ -123,17 +147,18 @@
}
private static HttpConnection getSSLConnection(InetSocketAddress addr,
- InetSocketAddress proxy,
- HttpRequestImpl request,
- String[] alpn) {
+ InetSocketAddress proxy, HttpRequestImpl request,
+ String[] alpn, Http2Connection http2) {
HttpClientImpl client = request.client();
if (proxy != null) {
return new SSLTunnelConnection(addr,
client,
proxy,
request.getAccessControlContext());
+ } else if (http2 == null) {
+ return new SSLConnection(addr, client, alpn);
} else {
- return new SSLConnection(addr, client, alpn);
+ return new AsyncSSLConnection(addr, client, alpn);
}
}
@@ -142,7 +167,8 @@
* none available.
*/
private static HttpConnection getConnectionImpl(InetSocketAddress addr,
- HttpRequestImpl request) {
+ HttpRequestImpl request, Http2Connection http2) {
+
HttpConnection c;
HttpClientImpl client = request.client();
InetSocketAddress proxy = request.proxy();
@@ -167,7 +193,7 @@
if (c != null) {
return c;
} else {
- return getSSLConnection(addr, proxy, request, alpn);
+ return getSSLConnection(addr, proxy, request, alpn, http2);
}
}
}
@@ -223,64 +249,16 @@
return address;
}
- void configureBlocking(boolean mode) throws IOException {
- channel().configureBlocking(mode);
+ synchronized void configureMode(Mode mode) throws IOException {
+ this.mode = mode;
+ if (mode == Mode.BLOCKING)
+ channel().configureBlocking(true);
+ else
+ channel().configureBlocking(false);
}
abstract ConnectionPool.CacheKey cacheKey();
- /*
- static PrintStream ps;
-
- static {
- try {
- String propval = Utils.getNetProperty("java.net.httpclient.showData");
- if (propval != null && propval.equalsIgnoreCase("true")) {
- ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- synchronized final void debugPrint(String s, ByteBuffer b) {
- ByteBuffer[] bufs = new ByteBuffer[1];
- bufs[0] = b;
- debugPrint(s, bufs, 0, 1);
- }
-
- synchronized final void debugPrint(String s,
- ByteBuffer[] bufs,
- int start,
- int number) {
- if (ps == null) {
- return;
- }
-
- ps.printf("\n%s:\n", s);
-
- for (int i=start; i<start+number; i++) {
- ByteBuffer b = bufs[i].duplicate();
- while (b.hasRemaining()) {
- int c = b.get();
- if (c == 10) {
- ps.printf("LF \n");
- } else if (c == 13) {
- ps.printf(" CR ");
- } else if (c == 0x20) {
- ps.printf("_");
- } else if (c > 0x20 && c <= 0x7F) {
- ps.printf("%c", (char)c);
- } else {
- ps.printf("0x%02x ", c);
- }
- }
- }
- ps.printf("\n---------------------\n");
- }
-
- */
-
// overridden in SSL only
SSLParameters sslParameters() {
return null;
@@ -296,7 +274,8 @@
/**
* Closes this connection, by returning the socket to its connection pool.
*/
- abstract void close();
+ @Override
+ public abstract void close();
/**
* Returns a ByteBuffer with data, or null if EOF.
@@ -356,12 +335,17 @@
}
@Override
- public final ByteBuffer getBuffer() {
- return client.getBuffer();
+ public final ByteBuffer getBuffer(int n) {
+ return client.getBuffer(n);
}
@Override
public final void returnBuffer(ByteBuffer buffer) {
client.returnBuffer(buffer);
}
+
+ @Override
+ public final void setMinBufferSize(int n) {
+ client.setMinBufferSize(n);
+ }
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java Fri May 06 06:23:30 2016 -0700
@@ -24,44 +24,22 @@
package java.net.http;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.TreeMap;
/**
* Implementation of HttpHeaders.
*/
-class HttpHeadersImpl implements HttpHeaders1 {
+class HttpHeadersImpl implements HttpHeaders {
- private final HashMap<String,List<String>> headers;
- private boolean isUnmodifiable = false;
+ private final TreeMap<String,List<String>> headers;
public HttpHeadersImpl() {
- headers = new HashMap<>();
- }
-
- /**
- * Replace all List<String> in headers with unmodifiable Lists. Call
- * this only after all headers are added. The headers HashMap
- * is wrapped with an unmodifiable HashMap in map()
- */
- @Override
- public void makeUnmodifiable() {
- if (isUnmodifiable)
- return;
-
- Set<String> keys = new HashSet<>(headers.keySet());
- for (String key : keys) {
- List<String> values = headers.remove(key);
- if (values != null) {
- headers.put(key, Collections.unmodifiableList(values));
- }
- }
- isUnmodifiable = true;
+ headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
}
@Override
@@ -88,7 +66,7 @@
public HttpHeadersImpl deepCopy() {
HttpHeadersImpl h1 = new HttpHeadersImpl();
- HashMap<String,List<String>> headers1 = h1.headers;
+ TreeMap<String,List<String>> headers1 = h1.headers;
Set<String> keys = headers.keySet();
for (String key : keys) {
List<String> vals = headers.get(key);
@@ -98,22 +76,13 @@
return h1;
}
- private List<String> getOrCreate(String name) {
- List<String> l = headers.get(name);
- if (l == null) {
- l = new LinkedList<>();
- headers.put(name, l);
- }
- return l;
- }
-
void addHeader(String name, String value) {
- List<String> l = getOrCreate(name);
- l.add(value);
+ headers.computeIfAbsent(name, k -> new LinkedList<>())
+ .add(value);
}
void setHeader(String name, String value) {
- List<String> l = getOrCreate(name);
+ List<String> l = headers.computeIfAbsent(name, k -> new LinkedList<>());
l.clear();
l.add(value);
}
@@ -122,7 +91,7 @@
public Optional<Long> firstValueAsLong(String name) {
List<String> l = headers.get(name);
if (l == null) {
- return Optional.ofNullable(null);
+ return Optional.empty();
} else {
String v = l.get(0);
Long lv = Long.parseLong(v);
@@ -133,4 +102,4 @@
void clear() {
headers.clear();
}
-}
+}
\ No newline at end of file
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java Fri May 06 06:23:30 2016 -0700
@@ -39,10 +39,11 @@
private HttpClient.Version version;
private final HttpClientImpl client;
private ProxySelector proxy;
- private long timeval = 0;
+ private long timeval;
public HttpRequestBuilderImpl(HttpClientImpl client, URI uri) {
this.client = client;
+ checkURI(uri);
this.uri = uri;
this.version = client.version();
this.userHeaders = new HttpHeadersImpl();
@@ -58,10 +59,17 @@
@Override
public HttpRequestBuilderImpl uri(URI uri) {
Objects.requireNonNull(uri);
+ checkURI(uri);
this.uri = uri;
return this;
}
+ private static void checkURI(URI uri) {
+ String scheme = uri.getScheme().toLowerCase();
+ if (!scheme.equals("https") && !scheme.equals("http"))
+ throw new IllegalArgumentException("invalid URI scheme");
+ }
+
@Override
public HttpRequestBuilderImpl followRedirects(HttpClient.Redirect follow) {
Objects.requireNonNull(follow);
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java Fri May 06 06:23:30 2016 -0700
@@ -30,16 +30,14 @@
import java.net.http.HttpClient.Version;
import java.net.http.HttpResponse.MultiProcessor;
import java.util.concurrent.CompletableFuture;
-import java.net.SocketPermission;
import java.security.AccessControlContext;
import java.security.AccessController;
-import java.util.Set;
import static java.net.http.HttpRedirectImpl.getRedirects;
import java.util.Locale;
class HttpRequestImpl extends HttpRequest {
- private final HttpHeadersImpl userHeaders;
+ private final ImmutableHeaders userHeaders;
private final HttpHeadersImpl systemHeaders;
private final URI uri;
private InetSocketAddress authority; // only used when URI not specified
@@ -56,6 +54,7 @@
private boolean receiving;
private AccessControlContext acc;
private final long timeval;
+ private Stream.PushGroup<?> pushGroup;
public HttpRequestImpl(HttpClientImpl client,
String method,
@@ -63,8 +62,8 @@
this.client = client;
this.method = method == null? "GET" : method;
this.userHeaders = builder.headers() == null ?
- new HttpHeadersImpl() : builder.headers();
- dropDisallowedHeaders();
+ new ImmutableHeaders() :
+ new ImmutableHeaders(builder.headers(), Utils.ALLOWED_HEADERS);
this.followRedirects = getRedirects(builder.followRedirects() == null ?
client.followRedirects() : builder.followRedirects());
this.systemHeaders = new HttpHeadersImpl();
@@ -90,15 +89,13 @@
HttpRequestImpl other) {
this.client = client;
this.method = method == null? "GET" : method;
- this.userHeaders = other.userHeaders == null ?
- new HttpHeadersImpl() : other.userHeaders;
- dropDisallowedHeaders();
+ this.userHeaders = other.userHeaders;
this.followRedirects = getRedirects(other.followRedirects() == null ?
client.followRedirects() : other.followRedirects());
this.systemHeaders = other.systemHeaders;
this.uri = uri;
this.expectContinue = other.expectContinue;
- this.secure = other.secure;
+ this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
this.requestProcessor = other.requestProcessor;
this.proxy = other.proxy;
this.version = other.version;
@@ -115,7 +112,7 @@
this.method = method;
this.followRedirects = getRedirects(client.followRedirects());
this.systemHeaders = new HttpHeadersImpl();
- this.userHeaders = new HttpHeadersImpl();
+ this.userHeaders = new ImmutableHeaders();
this.uri = null;
this.proxy = null;
this.requestProcessor = HttpRequest.noBody();
@@ -132,16 +129,52 @@
return client;
}
+ /**
+ * Creates a HttpRequestImpl from the given set of Headers and the associated
+ * "parent" request. Fields not taken from the headers are taken from the
+ * parent.
+ */
+ static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
+ HttpHeadersImpl headers) throws IOException {
+
+ return new HttpRequestImpl(parent, headers);
+ }
+
+ // only used for push requests
+ private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers) throws IOException {
+ this.method = headers.firstValue(":method")
+ .orElseThrow(() -> new IOException("No method in Push Promise"));
+ String path = headers.firstValue(":path")
+ .orElseThrow(() -> new IOException("No path in Push Promise"));
+ String scheme = headers.firstValue(":scheme")
+ .orElseThrow(() -> new IOException("No scheme in Push Promise"));
+ String authority = headers.firstValue(":authority")
+ .orElseThrow(() -> new IOException("No authority in Push Promise"));
+ StringBuilder sb = new StringBuilder();
+ sb.append(scheme).append("://").append(authority).append(path);
+ this.uri = URI.create(sb.toString());
+
+ this.client = parent.client;
+ this.userHeaders = new ImmutableHeaders(headers, Utils.ALLOWED_HEADERS);
+ this.followRedirects = parent.followRedirects;
+ this.systemHeaders = parent.systemHeaders;
+ this.expectContinue = parent.expectContinue;
+ this.secure = parent.secure;
+ this.requestProcessor = parent.requestProcessor;
+ this.proxy = parent.proxy;
+ this.version = parent.version;
+ this.acc = parent.acc;
+ this.exchange = parent.exchange;
+ this.timeval = parent.timeval;
+ }
@Override
public String toString() {
- return (uri == null ? "" : uri.toString()) + "/" + method + "("
- + hashCode() + ")";
+ return (uri == null ? "" : uri.toString()) + " " + method;
}
@Override
public HttpHeaders headers() {
- userHeaders.makeUnmodifiable();
return userHeaders;
}
@@ -154,21 +187,6 @@
systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
}
- private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
- "authorization", "connection", "cookie", "content-length",
- "date", "expect", "from", "host", "origin", "proxy-authorization",
- "referer", "user-agent", "upgrade", "via", "warning");
-
-
- // we silently drop headers that are disallowed
- private void dropDisallowedHeaders() {
- Set<String> hdrnames = userHeaders.directMap().keySet();
-
- hdrnames.removeIf((s) ->
- DISALLOWED_HEADERS_SET.contains(s.toLowerCase())
- );
- }
-
private synchronized void receiving() {
if (receiving) {
throw new IllegalStateException("already receiving response");
@@ -176,6 +194,10 @@
receiving = true;
}
+ synchronized Stream.PushGroup<?> pushGroup() {
+ return pushGroup;
+ }
+
/*
* Response filters may result in a new HttpRequestImpl being created
* (but still associated with the same API HttpRequest) and the process
@@ -200,10 +222,25 @@
.thenApply((r) -> (HttpResponse)r);
}
- public <U> CompletableFuture<U>
- sendAsyncMulti(HttpResponse.MultiProcessor<U> rspproc) {
- // To change body of generated methods, choose Tools | Templates.
- throw new UnsupportedOperationException("Not supported yet.");
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public synchronized <U> CompletableFuture<U>
+ multiResponseAsync(MultiProcessor<U> rspproc) {
+ if (System.getSecurityManager() != null) {
+ acc = AccessController.getContext();
+ }
+ this.pushGroup = new Stream.PushGroup<>(rspproc, this);
+ CompletableFuture<HttpResponse> cf = pushGroup.mainResponse();
+ responseAsync()
+ .whenComplete((HttpResponse r, Throwable t) -> {
+ if (r != null)
+ cf.complete(r);
+ else
+ cf.completeExceptionally(t);
+ pushGroup.pushError(t);
+ });
+ return (CompletableFuture<U>)pushGroup.groupResult();
}
@Override
@@ -255,7 +292,7 @@
@Override
public URI uri() { return uri; }
- HttpHeadersImpl getUserHeaders() { return userHeaders; }
+ HttpHeaders getUserHeaders() { return userHeaders; }
HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
@@ -275,11 +312,4 @@
}
long timeval() { return timeval; }
-
- @Override
- public <U> CompletableFuture<U>
- multiResponseAsync(MultiProcessor<U> rspproc) {
- //To change body of generated methods, choose Tools | Templates.
- throw new UnsupportedOperationException("Not supported yet.");
- }
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java Fri May 06 06:23:30 2016 -0700
@@ -200,8 +200,12 @@
if (n == -1) {
throw new IOException("Bad Content-Disposition type");
}
- String disposition = dispoHeader.substring(n + 9,
- dispoHeader.lastIndexOf(';'));
+ int lastsemi = dispoHeader.lastIndexOf(';');
+ String disposition;
+ if (lastsemi < n)
+ disposition = dispoHeader.substring(n + 9);
+ else
+ disposition = dispoHeader.substring(n + 9, lastsemi);
file = Paths.get(directory.toString(), disposition);
fc = FileChannel.open(file, openOptions);
return null;
@@ -727,11 +731,14 @@
}
private CompletableFuture<Path> getBody(HttpRequest req,
- CompletableFuture<HttpResponse> cf) {
+ CompletableFuture<? extends HttpResponse> cf) {
URI u = req.uri();
String path = u.getPath();
+ if (path.startsWith("/"))
+ path = path.substring(1);
+ final String fpath = path;
return cf.thenCompose((HttpResponse resp) -> {
- return resp.bodyAsync(HttpResponse.asFile(destination.resolve(path)));
+ return resp.bodyAsync(HttpResponse.asFile(destination.resolve(fpath)));
});
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java Fri May 06 06:23:30 2016 -0700
@@ -26,6 +26,7 @@
package java.net.http;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.security.AccessControlContext;
@@ -42,17 +43,18 @@
int responseCode;
Exchange exchange;
HttpRequestImpl request;
- HttpHeaders1 headers;
- HttpHeaders1 trailers;
+ HttpHeaders headers;
+ HttpHeaders trailers;
SSLParameters sslParameters;
URI uri;
HttpClient.Version version;
AccessControlContext acc;
RawChannel rawchan;
HttpConnection connection;
+ final Stream stream;
- public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders1 headers,
- HttpHeaders1 trailers, SSLParameters sslParameters,
+ public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders headers,
+ HttpHeaders trailers, SSLParameters sslParameters,
HttpClient.Version version, HttpConnection connection) {
this.responseCode = responseCode;
this.exchange = exch;
@@ -63,6 +65,23 @@
this.uri = request.uri();
this.version = version;
this.connection = connection;
+ this.stream = null;
+ }
+
+ // A response to a PUSH_PROMISE
+ public HttpResponseImpl(int responseCode, HttpRequestImpl pushRequest,
+ ImmutableHeaders headers,
+ Stream stream, SSLParameters sslParameters) {
+ this.responseCode = responseCode;
+ this.exchange = null;
+ this.request = pushRequest;
+ this.headers = headers;
+ this.trailers = null;
+ this.sslParameters = sslParameters;
+ this.uri = request.uri(); // TODO: take from headers
+ this.version = HttpClient.Version.HTTP_2;
+ this.connection = null;
+ this.stream = stream;
}
@Override
@@ -77,26 +96,35 @@
@Override
public HttpHeaders headers() {
- headers.makeUnmodifiable();
return headers;
}
@Override
public HttpHeaders trailers() {
- trailers.makeUnmodifiable();
return trailers;
}
@Override
public <T> T body(java.net.http.HttpResponse.BodyProcessor<T> processor) {
- return exchange.responseBody(processor);
+ try {
+ if (exchange != null) {
+ return exchange.responseBody(processor);
+ } else {
+ return stream.responseBody(processor);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
@Override
public <T> CompletableFuture<T> bodyAsync(java.net.http.HttpResponse.BodyProcessor<T> processor) {
acc = AccessController.getContext();
- return exchange.responseBodyAsync(processor);
+ if (exchange != null)
+ return exchange.responseBodyAsync(processor);
+ else
+ return stream.responseBodyAsync(processor);
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
+import java.util.function.Predicate;
+
+/**
+ * Immutable HttpHeaders constructed from mutable HttpHeadersImpl.
+ */
+
+class ImmutableHeaders implements HttpHeaders {
+
+ private final Map<String,List<String>> map;
+
+ @SuppressWarnings("unchecked")
+ ImmutableHeaders() {
+ map = (Map<String,List<String>>)Collections.EMPTY_MAP;
+ }
+ // TODO: fix lower case issue. Must be lc for http/2 compares ignoreCase for http/1
+ ImmutableHeaders(HttpHeadersImpl h, Predicate<String> keyAllowed) {
+ Map<String,List<String>> src = h.directMap();
+ Map<String,List<String>> m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+ src.forEach((key, value) -> {
+ if (keyAllowed.test(key))
+ m.put(key, Collections.unmodifiableList(value));
+ });
+ map = Collections.unmodifiableMap(m);
+ }
+
+ @Override
+ public Optional<String> firstValue(String name) {
+ List<String> l = map.get(name);
+ String v = l == null ? null : l.get(0);
+ return Optional.ofNullable(v);
+ }
+
+ @Override
+ public Optional<Long> firstValueAsLong(String name) {
+ return firstValue(name).map((v -> Long.parseLong(v)));
+ }
+
+ @Override
+ public List<String> allValues(String name) {
+ return map.get(name);
+ }
+
+ @Override
+ public Map<String, List<String>> map() {
+ return map;
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java Fri May 06 06:23:30 2016 -0700
@@ -26,7 +26,9 @@
import java.util.Locale;
/**
- * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content
+ * -Djava.net.HttpClient.log=
+ * errors,requests,headers,
+ * frames[:type:type2:..],content,ssl,trace
*
* Any of errors, requests, headers or content are optional.
*
@@ -47,6 +49,7 @@
public static final int CONTENT = 0x8;
public static final int FRAMES = 0x10;
public static final int SSL = 0x20;
+ public static final int TRACE = 0x40;
static int logging;
// Frame types: "control", "data", "window", "all"
@@ -81,8 +84,11 @@
case "ssl":
logging |= SSL;
break;
+ case "trace":
+ logging |= TRACE;
+ break;
case "all":
- logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS;
+ logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE;
break;
}
if (val.startsWith("frames")) {
@@ -130,6 +136,10 @@
return (logging & HEADERS) != 0;
}
+ static boolean trace() {
+ return (logging & TRACE) != 0;
+ }
+
static boolean ssl() {
return (logging & SSL) != 0;
}
@@ -138,9 +148,9 @@
return (logging & FRAMES) != 0;
}
- static void logError(String s) {
+ static void logError(String s, Object... s1) {
if (errors())
- logger.log(Level.INFO, "ERROR: " + s);
+ logger.log(Level.INFO, "ERROR: " + s, s1);
}
static void logError(Throwable t) {
@@ -150,24 +160,50 @@
}
}
- static void logSSL(String s) {
+ static void logSSL(String s, Object... s1) {
if (ssl())
- logger.log(Level.INFO, "SSL: " + s);
+ logger.log(Level.INFO, "SSL: " + s, s1);
+ }
+
+ static void logTrace(String s, Object... s1) {
+ if (trace()) {
+ String format = "TRACE: " + s;
+ logger.log(Level.INFO, format, s1);
+ }
+ }
+
+ static void logRequest(String s, Object... s1) {
+ if (requests())
+ logger.log(Level.INFO, "REQUEST: " + s, s1);
+ }
+
+ static void logResponse(String s, Object... s1) {
+ if (requests())
+ logger.log(Level.INFO, "RESPONSE: " + s, s1);
}
- static void logRequest(String s) {
- if (requests())
- logger.log(Level.INFO, "REQUEST: " + s);
+ static void logHeaders(String s, Object... s1) {
+ if (headers())
+ logger.log(Level.INFO, "HEADERS: " + s, s1);
+ }
+// START HTTP2
+ static boolean loggingFrame(Class<? extends Http2Frame> clazz) {
+ if (frametypes == ALL) {
+ return true;
+ }
+ if (clazz == DataFrame.class) {
+ return (frametypes & DATA) != 0;
+ } else if (clazz == WindowUpdateFrame.class) {
+ return (frametypes & WINDOW_UPDATES) != 0;
+ } else {
+ return (frametypes & CONTROL) != 0;
+ }
}
- static void logResponse(String s) {
- if (requests())
- logger.log(Level.INFO, "RESPONSE: " + s);
- }
-
- static void logHeaders(String s) {
- if (headers())
- logger.log(Level.INFO, "HEADERS: " + s);
+ static void logFrames(Http2Frame f, String direction) {
+ if (frames() && loggingFrame(f.getClass())) {
+ logger.log(Level.INFO, "FRAME: " + direction + ": " + f.toString());
+ }
}
// not instantiable
--- a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java Fri May 06 06:23:30 2016 -0700
@@ -54,7 +54,7 @@
final static int DEFAULT_MAX_ATTEMPTS = 5;
final static int max_attempts = Utils.getIntegerNetProperty(
- "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS
+ "java.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS
);
private final List<HeaderFilter> filters;
@@ -187,8 +187,7 @@
public CompletableFuture<HttpResponseImpl> responseAsync(Void v) {
CompletableFuture<HttpResponseImpl> cf;
if (++attempts > max_attempts) {
- cf = new CompletableFuture<>();
- cf.completeExceptionally(new IOException("Too many retries"));
+ cf = CompletableFuture.failedFuture(new IOException("Too many retries"));
} else {
if (currentreq.timeval() != 0) {
// set timer
@@ -241,7 +240,6 @@
* completed exceptionally.
*/
private CompletableFuture<HttpResponseImpl> getExceptionalCF(Throwable t) {
- CompletableFuture<HttpResponseImpl> error = new CompletableFuture<>();
if ((t instanceof CompletionException) || (t instanceof ExecutionException)) {
if (t.getCause() != null) {
t = t.getCause();
@@ -250,8 +248,7 @@
if (cancelled && t instanceof IOException) {
t = new HttpTimeoutException("request timed out");
}
- error.completeExceptionally(t);
- return error;
+ return CompletableFuture.failedFuture(t);
}
<T> T responseBody(HttpResponse.BodyProcessor<T> processor) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+
+/**
+ * Contains all parameters for outgoing headers. Is converted to
+ * HeadersFrame and ContinuationFrames by Http2Connection.
+ */
+class OutgoingHeaders extends Http2Frame {
+
+ int streamDependency;
+ int weight;
+ boolean exclusive;
+ Stream stream;
+
+ public static final int PRIORITY = 0x20;
+
+ HttpHeaders user, system;
+
+ OutgoingHeaders(HttpHeaders hdrs1, HttpHeaders hdrs2, Stream stream) {
+ this.user = hdrs2;
+ this.system = hdrs1;
+ this.stream = stream;
+ }
+
+ public void setPriority(int streamDependency, boolean exclusive, int weight) {
+ this.streamDependency = streamDependency;
+ this.exclusive = exclusive;
+ this.weight = weight;
+ this.flags |= PRIORITY;
+ }
+
+ public int getStreamDependency() {
+ return streamDependency;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public boolean getExclusive() {
+ return exclusive;
+ }
+
+ public Stream getStream() {
+ return stream;
+ }
+
+ public HttpHeaders getUserHeaders() {
+ return user;
+ }
+
+ public HttpHeaders getSystemHeaders() {
+ return system;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ void computeLength() {
+ //To change body of generated methods, choose Tools | Templates.
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java Fri May 06 06:23:30 2016 -0700
@@ -43,4 +43,9 @@
static <T, U> Pair<T, U> pair(T first, U second) {
return new Pair<>(first, second);
}
+
+ @Override
+ public String toString() {
+ return "(" + first + ", " + second + ")";
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class PingFrame extends Http2Frame {
+
+ PingFrame() {
+ type = TYPE;
+ }
+
+ byte[] data;
+
+ public final static int TYPE = 0x6;
+
+ // Flags
+ public static final int ACK = 0x1;
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case ACK:
+ return "ACK";
+ }
+ return super.flagAsString(flag);
+ }
+
+ public void setData(byte[] data) {
+ if (data.length != 8) {
+ throw new IllegalArgumentException("Ping data not 8 bytes");
+ }
+ this.data = data;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if (length != 8) {
+ throw new IOException("Invalid Ping frame");
+ }
+ data = bc.getBytes(8);
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ if (data == null) {
+ data = new byte[] {0, 0, 0, 0, 0 ,0, 0, 0};
+ }
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(8);
+ buf.put(data);
+ }
+
+ @Override
+ void computeLength() {
+ length = 8;
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java Fri May 06 06:23:30 2016 -0700
@@ -31,20 +31,43 @@
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
/**
- * Plain raw TCP connection direct to destination
+ * Plain raw TCP connection direct to destination. 2 modes
+ * 1) Blocking used by http/1. In this case the connect is actually non
+ * blocking but the request is sent blocking. The first byte of a response
+ * is received non-blocking and the remainder of the response is received
+ * blocking
+ * 2) Non-blocking. In this case (for http/2) the connection is actually opened
+ * blocking but all reads and writes are done non-blocking under the
+ * control of a Http2Connection object.
*/
-class PlainHttpConnection extends HttpConnection {
+class PlainHttpConnection extends HttpConnection implements AsyncConnection {
protected SocketChannel chan;
private volatile boolean connected;
private boolean closed;
+ Consumer<ByteBuffer> asyncReceiver;
+ Consumer<Throwable> errorReceiver;
+ Queue<ByteBuffer> asyncOutputQ;
+ final Object reading = new Object();
+ final Object writing = new Object();
- class ConnectEvent extends AsyncEvent implements AsyncEvent.Blocking {
+ @Override
+ public void startReading() {
+ try {
+ client.registerEvent(new ReadEvent());
+ } catch (IOException e) {
+ shutdown();
+ }
+ }
+
+ class ConnectEvent extends AsyncEvent {
CompletableFuture<Void> cf;
ConnectEvent(CompletableFuture<Void> cf) {
+ super(AsyncEvent.BLOCKING);
this.cf = cf;
}
@@ -112,14 +135,62 @@
@Override
long write(ByteBuffer[] buffers, int start, int number) throws IOException {
- //debugPrint("Send", buffers, start, number);
- return chan.write(buffers, start, number);
+ if (mode != Mode.ASYNC)
+ return chan.write(buffers, start, number);
+ // async
+ synchronized(writing) {
+ int qlen = asyncOutputQ.size();
+ ByteBuffer[] bufs = Utils.reduce(buffers, start, number);
+ long n = Utils.remaining(bufs);
+ asyncOutputQ.putAll(bufs);
+ if (qlen == 0)
+ asyncOutput();
+ return n;
+ }
+ }
+
+ ByteBuffer asyncBuffer = null;
+
+ void asyncOutput() {
+ synchronized (writing) {
+ try {
+ while (true) {
+ if (asyncBuffer == null) {
+ asyncBuffer = asyncOutputQ.poll();
+ if (asyncBuffer == null) {
+ return;
+ }
+ }
+ if (!asyncBuffer.hasRemaining()) {
+ asyncBuffer = null;
+ continue;
+ }
+ int n = chan.write(asyncBuffer);
+ //System.err.printf("Written %d bytes to chan\n", n);
+ if (n == 0) {
+ client.registerEvent(new WriteEvent());
+ return;
+ }
+ }
+ } catch (IOException e) {
+ shutdown();
+ }
+ }
}
@Override
long write(ByteBuffer buffer) throws IOException {
- //debugPrint("Send", buffer);
- return chan.write(buffer);
+ if (mode != Mode.ASYNC)
+ return chan.write(buffer);
+ // async
+ synchronized(writing) {
+ int qlen = asyncOutputQ.size();
+ long n = buffer.remaining();
+ asyncOutputQ.put(buffer);
+ if (qlen == 0)
+ asyncOutput();
+ return n;
+ }
}
@Override
@@ -131,7 +202,7 @@
* Close this connection
*/
@Override
- synchronized void close() {
+ public synchronized void close() {
if (closed)
return;
closed = true;
@@ -155,14 +226,49 @@
return buf;
}
+ void shutdown() {
+ close();
+ errorReceiver.accept(new IOException("Connection aborted"));
+ }
+
+ void asyncRead() {
+ synchronized (reading) {
+ try {
+ while (true) {
+ ByteBuffer buf = getBuffer();
+ int n = chan.read(buf);
+ //System.err.printf("Read %d bytes from chan\n", n);
+ if (n == -1) {
+ throw new IOException();
+ }
+ if (n == 0) {
+ returnBuffer(buf);
+ return;
+ }
+ buf.flip();
+ asyncReceiver.accept(buf);
+ }
+ } catch (IOException e) {
+ shutdown();
+ }
+ }
+ }
+
@Override
protected int readImpl(ByteBuffer buf) throws IOException {
int mark = buf.position();
- int n = chan.read(buf);
+ int n;
+ // FIXME: this hack works in conjunction with the corresponding change
+ // in java.net.http.RawChannel.registerEvent
+ if ((n = buffer.remaining()) != 0) {
+ buf.put(buffer);
+ } else {
+ n = chan.read(buf);
+ }
if (n == -1) {
return -1;
}
- Utils.flipToMark(buffer, mark);
+ Utils.flipToMark(buf, mark);
String s = "Receive (" + n + " bytes) ";
//debugPrint(s, buf);
return n;
@@ -178,10 +284,67 @@
return connected;
}
- class ReceiveResponseEvent extends AsyncEvent implements AsyncEvent.Blocking {
+ // used for all output in HTTP/2
+ class WriteEvent extends AsyncEvent {
+ WriteEvent() {
+ super(0);
+ }
+
+ @Override
+ public SelectableChannel channel() {
+ return chan;
+ }
+
+ @Override
+ public int interestOps() {
+ return SelectionKey.OP_WRITE;
+ }
+
+ @Override
+ public void handle() {
+ asyncOutput();
+ }
+
+ @Override
+ public void abort() {
+ shutdown();
+ }
+ }
+
+ // used for all input in HTTP/2
+ class ReadEvent extends AsyncEvent {
+ ReadEvent() {
+ super(AsyncEvent.REPEATING); // && !BLOCKING
+ }
+
+ @Override
+ public SelectableChannel channel() {
+ return chan;
+ }
+
+ @Override
+ public int interestOps() {
+ return SelectionKey.OP_READ;
+ }
+
+ @Override
+ public void handle() {
+ asyncRead();
+ }
+
+ @Override
+ public void abort() {
+ shutdown();
+ }
+
+ }
+
+ // used in blocking channels only
+ class ReceiveResponseEvent extends AsyncEvent {
CompletableFuture<Void> cf;
ReceiveResponseEvent(CompletableFuture<Void> cf) {
+ super(AsyncEvent.BLOCKING);
this.cf = cf;
}
@Override
@@ -216,6 +379,15 @@
}
@Override
+ public synchronized void setAsyncCallbacks(Consumer<ByteBuffer> asyncReceiver,
+ Consumer<Throwable> errorReceiver) {
+ this.asyncReceiver = asyncReceiver;
+ this.errorReceiver = errorReceiver;
+ asyncOutputQ = new Queue<>();
+ asyncOutputQ.registerPutCallback(this::asyncOutput);
+ }
+
+ @Override
CompletableFuture<Void> whenReceivingResponse() {
CompletableFuture<Void> cf = new CompletableFuture<>();
try {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java Fri May 06 06:23:30 2016 -0700
@@ -111,7 +111,7 @@
}
@Override
- void close() {
+ public void close() {
delegate.close();
connected = false;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class PriorityFrame extends Http2Frame {
+
+ int streamDependency;
+ int weight;
+ boolean exclusive;
+
+ public final static int TYPE = 0x2;
+
+ PriorityFrame() {
+ type = TYPE;
+ }
+
+ public PriorityFrame(int streamDependency, boolean exclusive, int weight) {
+ this.streamDependency = streamDependency;
+ this.exclusive = exclusive;
+ this.weight = weight;
+ this.type = TYPE;
+ }
+
+ int streamDependency() {
+ return streamDependency;
+ }
+
+ int weight() {
+ return weight;
+ }
+
+ boolean exclusive() {
+ return exclusive;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ int x = bc.getInt();
+ exclusive = (x & 0x80000000) != 0;
+ streamDependency = x & 0x7fffffff;
+ weight = bc.getByte();
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(5);
+ int x = exclusive ? (1 << 31) + streamDependency : streamDependency;
+ buf.putInt(x);
+ buf.put((byte)weight);
+ }
+
+ @Override
+ void computeLength() {
+ length = 5;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,119 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class PushPromiseFrame extends HeaderFrame {
+
+ int padLength;
+ int promisedStream;
+
+ PushPromiseFrame() {
+ type = TYPE;
+ }
+
+ public static final int TYPE = 0x5;
+
+ // Flags
+ public static final int END_HEADERS = 0x4;
+ public static final int PADDED = 0x8;
+
+ @Override
+ public String toString() {
+ return super.toString() + " promisedStreamid: " + promisedStream
+ + " headerLength: " + headerLength;
+ }
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case PADDED:
+ return "PADDED";
+ case END_HEADERS:
+ return "END_HEADERS";
+ }
+ return super.flagAsString(flag);
+ }
+
+ public void setPadLength(int padLength) {
+ this.padLength = padLength;
+ flags |= PADDED;
+ }
+
+ public void setPromisedStream(int stream) {
+ this.promisedStream = stream;
+ }
+
+ public int getPromisedStream() {
+ return promisedStream;
+ }
+
+ /**
+ */
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if ((flags & PADDED) != 0) {
+ padLength = bc.getByte();
+ headerLength = length - (padLength + 5);
+ } else
+ headerLength = length - 4;
+
+ promisedStream = bc.getInt() & 0x7fffffff;
+ headerBlocks = bc.getBuffers(headerLength);
+ }
+
+ @Override
+ void computeLength() {
+ int len = 0;
+ if ((flags & PADDED) != 0) {
+ len += (1 + padLength);
+ }
+ len += (4 + headerLength);
+ this.length = len;
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(length);
+ if ((flags & PADDED) != 0) {
+ buf.put((byte)padLength);
+ }
+ buf.putInt(promisedStream);
+ for (int i=0; i<headerBlocks.length; i++) {
+ bg.addByteBuffer(headerBlocks[i]);
+ }
+ if ((flags & PADDED) != 0) {
+ bg.addPadding(padLength);
+ }
+ }
+
+ @Override
+ public boolean endHeaders() {
+ return getFlag(END_HEADERS);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Queue.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,143 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.LinkedList;
+
+// Each stream has one of these for input. Each Http2Connection has one
+// for output. Can be used blocking or asynchronously.
+
+class Queue<T> implements Closeable {
+
+ private final LinkedList<T> q = new LinkedList<>();
+ private volatile boolean closed = false;
+ private Runnable callback;
+ private boolean forceCallback;
+ private int waiters; // true if someone waiting
+
+ synchronized void putAll(T[] objs) throws IOException {
+ if (closed) {
+ throw new IOException("stream closed");
+ }
+ boolean wasEmpty = q.isEmpty();
+
+ for (T obj : objs) {
+ q.add(obj);
+ }
+
+ if (waiters > 0)
+ notifyAll();
+
+ if (wasEmpty || forceCallback) {
+ forceCallback = false;
+ if (callback != null) {
+ callback.run();
+ }
+ }
+ }
+
+ synchronized int size() {
+ return q.size();
+ }
+
+ synchronized void put(T obj) throws IOException {
+ if (closed) {
+ throw new IOException("stream closed");
+ }
+
+ q.add(obj);
+ if (waiters > 0)
+ notifyAll();
+
+ if (q.size() == 1 || forceCallback) {
+ forceCallback = false;
+ if (callback != null) {
+ callback.run();
+ }
+ }
+ }
+
+ /**
+ * callback is invoked any time put is called where
+ * the Queue was empty.
+ */
+ synchronized void registerPutCallback(Runnable callback) {
+ this.callback = callback;
+ if (callback != null && q.size() > 0)
+ callback.run();
+ }
+
+ @Override
+ public synchronized void close() {
+ closed = true;
+ notifyAll();
+ }
+
+ synchronized T take() throws IOException {
+ if (closed) {
+ throw new IOException("stream closed");
+ }
+ try {
+ while (q.size() == 0) {
+ waiters++;
+ wait();
+ waiters--;
+ }
+ return q.removeFirst();
+ } catch (InterruptedException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ public synchronized T poll() throws IOException {
+ if (closed)
+ throw new IOException("stream closed");
+
+ if (q.isEmpty())
+ return null;
+ T res = q.removeFirst();
+ return res;
+ }
+
+ public synchronized T[] pollAll(T[] type) throws IOException {
+ T[] ret = q.toArray(type);
+ q.clear();
+ return ret;
+ }
+
+ public synchronized void pushback(T v) {
+ forceCallback = true;
+ q.addFirst(v);
+ }
+
+ public synchronized void pushbackAll(T[] v) {
+ forceCallback = true;
+ for (int i=v.length-1; i>=0; i--) {
+ q.addFirst(v[i]);
+ }
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java Fri May 06 06:23:30 2016 -0700
@@ -28,18 +28,18 @@
import java.nio.channels.ByteChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
-/**
- * Used to implement WebSocket. Each RawChannel corresponds to
- * a TCP connection (SocketChannel) but is connected to a Selector
- * and an ExecutorService for invoking the send and receive callbacks
- * Also includes SSL processing.
- */
-class RawChannel implements ByteChannel, GatheringByteChannel {
+//
+// Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
+// (SocketChannel) but is connected to a Selector and an ExecutorService for
+// invoking the send and receive callbacks. Also includes SSL processing.
+//
+final class RawChannel implements ByteChannel, GatheringByteChannel {
private final HttpClientImpl client;
private final HttpConnection connection;
- private boolean closed;
+ private volatile boolean closed;
private interface RawEvent {
@@ -50,8 +50,6 @@
void handle();
}
- interface BlockingEvent extends RawEvent { }
-
interface NonBlockingEvent extends RawEvent { }
RawChannel(HttpClientImpl client, HttpConnection connection) {
@@ -64,39 +62,40 @@
private final RawEvent re;
RawAsyncEvent(RawEvent re) {
+ super(AsyncEvent.BLOCKING); // BLOCKING & !REPEATING
this.re = re;
}
+ RawAsyncEvent(RawEvent re, int flags) {
+ super(flags);
+ this.re = re;
+ }
+
+ @Override
public SelectableChannel channel() {
return connection.channel();
}
// must return the selector interest op flags OR'd
+ @Override
public int interestOps() {
return re.interestOps();
}
// called when event occurs
+ @Override
public void handle() {
re.handle();
}
- public void abort() {}
+ @Override
+ public void abort() { }
}
- private class BlockingRawAsyncEvent extends RawAsyncEvent
- implements AsyncEvent.Blocking {
-
- BlockingRawAsyncEvent(RawEvent re) {
- super(re);
- }
- }
-
- private class NonBlockingRawAsyncEvent extends RawAsyncEvent
- implements AsyncEvent.NonBlocking {
+ private class NonBlockingRawAsyncEvent extends RawAsyncEvent {
NonBlockingRawAsyncEvent(RawEvent re) {
- super(re);
+ super(re, 0); // !BLOCKING & !REPEATING
}
}
@@ -105,17 +104,24 @@
* (i.e. register new event for each callback)
*/
public void registerEvent(RawEvent event) throws IOException {
- if (event instanceof BlockingEvent) {
- client.registerEvent(new BlockingRawAsyncEvent(event));
- } else if (event instanceof NonBlockingEvent) {
+ if (!(event instanceof NonBlockingEvent)) {
+ throw new InternalError();
+ }
+ if ((event.interestOps() & SelectionKey.OP_READ) != 0
+ && connection.buffer.hasRemaining()) {
+ // FIXME: a hack to deal with leftovers from previous reads into an
+ // internal buffer (works in conjunction with change in
+ // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer)
+ connection.channel().configureBlocking(false);
+ event.handle();
+ } else {
client.registerEvent(new NonBlockingRawAsyncEvent(event));
- } else {
- throw new InternalError();
}
}
@Override
public int read(ByteBuffer dst) throws IOException {
+ assert !connection.channel().isBlocking();
return connection.read(dst);
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java Fri May 06 06:23:30 2016 -0700
@@ -33,17 +33,19 @@
HttpRequestImpl requestImpl;
HttpRequest request;
HttpClientImpl client;
+ HttpClient.Redirect policy;
String method;
final static int DEFAULT_MAX_REDIRECTS = 5;
URI uri;
final static int max_redirects = Utils.getIntegerNetProperty(
- "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS
+ "java.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS
);
@Override
public void request(HttpRequestImpl r) throws IOException {
this.request = r;
+ this.policy = request.followRedirects();
this.client = r.getClient();
this.method = r.method();
this.requestImpl = r;
@@ -61,7 +63,7 @@
*/
private HttpRequestImpl handleResponse(HttpResponseImpl r) {
int rcode = r.statusCode();
- if (rcode == 200) {
+ if (rcode == 200 || policy == HttpClient.Redirect.NEVER) {
return null;
}
if (rcode >= 300 && rcode <= 399) {
@@ -79,6 +81,7 @@
private URI getRedirectedURI(HttpHeaders headers) {
URI redirectedURI;
+ String ss = headers.firstValue("Location").orElse("Not present");
redirectedURI = headers.firstValue("Location")
.map((s) -> URI.create(s))
.orElseThrow(() -> new UncheckedIOException(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,61 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class ResetFrame extends ErrorFrame {
+
+ public final static int TYPE = 0x3;
+
+ // See ErrorFrame for error values
+
+ ResetFrame() {
+ type = TYPE;
+ }
+
+ public ResetFrame(int errorCode) {
+ this.errorCode = errorCode;
+ this.type = TYPE;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ errorCode = bc.getInt();
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(4);
+ buf.putInt(errorCode);
+ }
+
+ @Override
+ void computeLength() {
+ length = 4;
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java Fri May 06 06:23:30 2016 -0700
@@ -48,7 +48,7 @@
*
* This class is not thread-safe
*/
-class ResponseHeaders implements HttpHeaders1 {
+class ResponseHeaders implements HttpHeaders {
static final int DATA_SIZE = 16 * 1024; // initial space for headers
static final int NUM_HEADERS = 50; // initial expected max number of headers
@@ -368,10 +368,6 @@
return Collections.unmodifiableList(l);
}
- @Override
- public void makeUnmodifiable() {
- }
-
// Delegates map to HashMap but converts keys to lower case
static class HeaderMap implements Map<String,List<String>> {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -121,13 +121,8 @@
}
@Override
- void close() {
- try {
- //System.err.println ("Closing: " + this);
- delegate.channel().close(); // TODO: proper close
- } catch (IOException ex) {
- Log.logError(ex.toString());
- }
+ public void close() {
+ Utils.close(delegate.channel());
}
@Override
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java Fri May 06 06:23:30 2016 -0700
@@ -29,13 +29,9 @@
import java.util.Arrays;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLSession;
+import javax.net.ssl.*;
import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*;
/**
@@ -60,16 +56,18 @@
engine.setUseClientMode(true);
SSLParameters sslp = client.sslParameters().orElse(null);
if (sslp == null) {
- sslp = context.getDefaultSSLParameters();
+ sslp = context.getSupportedSSLParameters();
}
sslParameters = Utils.copySSLParameters(sslp);
if (alpn != null) {
sslParameters.setApplicationProtocols(alpn);
Log.logSSL("Setting application protocols: " + Arrays.toString(alpn));
} else {
- Log.logSSL("Warning no application protocols proposed!");
+ Log.logSSL("No application protocols proposed");
}
engine.setSSLParameters(sslParameters);
+ engine.setEnabledCipherSuites(sslp.getCipherSuites());
+ engine.setEnabledProtocols(sslp.getProtocols());
wrapper = new EngineWrapper(chan, engine);
this.chan = chan;
this.client = client;
@@ -268,7 +266,7 @@
do {
if (needData) {
do {
- x = chan.read (unwrap_src);
+ x = chan.read (unwrap_src);
} while (x == 0);
if (x == -1) {
throw new IOException ("connection closed for reading");
@@ -440,6 +438,27 @@
}
}
+ static void printParams(SSLParameters p) {
+ System.out.println("SSLParameters:");
+ if (p == null) {
+ System.out.println("Null params");
+ return;
+ }
+ for (String cipher : p.getCipherSuites()) {
+ System.out.printf("cipher: %s\n", cipher);
+ }
+ for (String approto : p.getApplicationProtocols()) {
+ System.out.printf("application protocol: %s\n", approto);
+ }
+ for (String protocol : p.getProtocols()) {
+ System.out.printf("protocol: %s\n", protocol);
+ }
+ if (p.getServerNames() != null)
+ for (SNIServerName sname : p.getServerNames()) {
+ System.out.printf("server name: %s\n", sname.toString());
+ }
+ }
+
String getSessionInfo() {
StringBuilder sb = new StringBuilder();
String application = engine.getApplicationProtocol();
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java Fri May 06 06:23:30 2016 -0700
@@ -130,12 +130,8 @@
}
@Override
- void close() {
- try {
- //System.err.println ("Closing: " + this);
- delegate.channel().close(); // TODO: proper close
- } catch (IOException ex) {
- }
+ public void close() {
+ Utils.close(delegate.channel());
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,165 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class SettingsFrame extends Http2Frame {
+
+ int[] parameters;
+
+ public static final int TYPE = 0x4;
+
+ // Flags
+ public static final int ACK = 0x1;
+
+ @Override
+ String flagAsString(int flag) {
+ switch (flag) {
+ case ACK:
+ return "ACK";
+ }
+ return super.flagAsString(flag);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(super.toString())
+ .append(" Settings: ");
+
+ for (int i = 0; i < MAX_PARAM; i++) {
+ if (parameters[i] != -1) {
+ sb.append(name(i))
+ .append("=")
+ .append(Integer.toString(parameters[i]))
+ .append(' ');
+ }
+ }
+ return sb.toString();
+ }
+
+ // Parameters
+ public static final int HEADER_TABLE_SIZE = 0x1;
+ public static final int ENABLE_PUSH = 0x2;
+ public static final int MAX_CONCURRENT_STREAMS = 0x3;
+ public static final int INITIAL_WINDOW_SIZE = 0x4;
+ public static final int MAX_FRAME_SIZE = 0x5;
+ public static final int MAX_HEADER_LIST_SIZE = 0x6;
+
+ private String name(int i) {
+ switch (i+1) {
+ case HEADER_TABLE_SIZE:
+ return "HEADER_TABLE_SIZE";
+ case ENABLE_PUSH:
+ return "ENABLE_PUSH";
+ case MAX_CONCURRENT_STREAMS:
+ return "MAX_CONCURRENT_STREAMS";
+ case INITIAL_WINDOW_SIZE:
+ return "INITIAL_WINDOW_SIZE";
+ case MAX_FRAME_SIZE:
+ return "MAX_FRAME_SIZE";
+ case MAX_HEADER_LIST_SIZE:
+ return "MAX_HEADER_LIST_SIZE";
+ }
+ return "unknown parameter";
+ }
+ public static final int MAX_PARAM = 0x6;
+
+ public SettingsFrame() {
+ type = TYPE;
+ parameters = new int [MAX_PARAM];
+ for (int i=0; i < parameters.length; i++) {
+ parameters[i] = -1;
+ }
+ }
+
+ public int getParameter(int paramID) {
+ if (paramID > MAX_PARAM) {
+ throw new IllegalArgumentException("illegal parameter");
+ }
+ return parameters[paramID-1];
+ }
+
+ public SettingsFrame setParameter(int paramID, int value) {
+ if (paramID > MAX_PARAM) {
+ throw new IllegalArgumentException("illegal parameter");
+ }
+ parameters[paramID-1] = value;
+ return this;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if (length % 6 != 0) {
+ throw new IOException("Protocol error: invalid settings frame");
+ }
+ int n = length / 6;
+ for (int i=0; i<n; i++) {
+ int id = bc.getShort();
+ int val = bc.getInt();
+ if (id > 0 || id <= MAX_PARAM) {
+ // a known parameter. Ignore otherwise
+ parameters[id-1] = val;
+ }
+ }
+ }
+
+ @Override
+ void computeLength() {
+ length = 0;
+ for (int i : parameters) {
+ if (i != -1) {
+ length += 6;
+ }
+ }
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(length);
+ for (int i = 0; i < MAX_PARAM; i++) {
+ if (parameters[i] != -1) {
+ buf.putShort((short)(i+1));
+ buf.putInt(parameters[i]);
+ }
+ }
+ }
+
+ private static final int K = 1024;
+
+ public static SettingsFrame getDefaultSettings() {
+ SettingsFrame f = new SettingsFrame();
+ // TODO: check these values
+ f.setParameter(ENABLE_PUSH, 1);
+ f.setParameter(HEADER_TABLE_SIZE, 4 * K);
+ f.setParameter(MAX_CONCURRENT_STREAMS, 35);
+ f.setParameter(INITIAL_WINDOW_SIZE, 16 * K);
+ f.setParameter(MAX_FRAME_SIZE, 16 * K);
+ return f;
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -24,78 +24,819 @@
package java.net.http;
+import sun.net.httpclient.hpack.DecodingCallback;
+
import java.io.IOException;
-import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
+import java.util.function.BiFunction;
import java.util.function.LongConsumer;
/**
- * Http/2 Stream
+ * Http/2 Stream handling.
+ *
+ * REQUESTS
+ *
+ * sendHeadersOnly() -- assembles HEADERS frame and puts on connection outbound Q
+ *
+ * sendRequest() -- sendHeadersOnly() + sendBody()
+ *
+ * sendBody() -- in calling thread: obeys all flow control (so may block)
+ * obtains data from request body processor and places on connection
+ * outbound Q.
+ *
+ * sendBodyAsync() -- calls sendBody() in an executor thread.
+ *
+ * sendHeadersAsync() -- calls sendHeadersOnly() which does not block
+ *
+ * sendRequestAsync() -- calls sendRequest() in an executor thread
+ *
+ * RESPONSES
+ *
+ * Multiple responses can be received per request. Responses are queued up on
+ * a LinkedList of CF<HttpResponse> and the the first one on the list is completed
+ * with the next response
+ *
+ * getResponseAsync() -- queries list of response CFs and returns first one
+ * if one exists. Otherwise, creates one and adds it to list
+ * and returns it. Completion is achieved through the
+ * incoming() upcall from connection reader thread.
+ *
+ * getResponse() -- calls getResponseAsync() and waits for CF to complete
+ *
+ * responseBody() -- in calling thread: blocks for incoming DATA frames on
+ * stream inputQ. Obeys remote and local flow control so may block.
+ * Calls user response body processor with data buffers.
+ *
+ * responseBodyAsync() -- calls responseBody() in an executor thread.
+ *
+ * incoming() -- entry point called from connection reader thread. Frames are
+ * either handled immediately without blocking or for data frames
+ * placed on the stream's inputQ which is consumed by the stream's
+ * reader thread.
+ *
+ * PushedStream sub class
+ * ======================
+ * Sending side methods are not used because the request comes from a PUSH_PROMISE
+ * frame sent by the server. When a PUSH_PROMISE is received the PushedStream
+ * is created. PushedStream does not use responseCF list as there can be only
+ * one response. The CF is created when the object created and when the response
+ * HEADERS frame is received the object is completed.
*/
class Stream extends ExchangeImpl {
- void debugPrint() {
- }
+ final Queue<Http2Frame> inputQ;
+
+ volatile int streamid;
+
+ long responseContentLen = -1;
+ long responseBytesProcessed = 0;
+ long requestContentLen;
+
+ Http2Connection connection;
+ HttpClientImpl client;
+ final HttpRequestImpl request;
+ final DecodingCallback rspHeadersConsumer;
+ HttpHeadersImpl responseHeaders;
+ final HttpHeadersImpl requestHeaders;
+ final HttpHeadersImpl requestPseudoHeaders;
+ HttpResponse.BodyProcessor<?> responseProcessor;
+ final HttpRequest.BodyProcessor requestProcessor;
+ HttpResponse response;
+
+ // state flags
+ boolean requestSent, responseReceived;
+
+ final FlowController userRequestFlowController =
+ new FlowController();
+ final FlowController remoteRequestFlowController =
+ new FlowController();
+ final FlowController responseFlowController =
+ new FlowController();
+
+ final ExecutorWrapper executor;
@Override
@SuppressWarnings("unchecked")
<T> CompletableFuture<T> responseBodyAsync(HttpResponse.BodyProcessor<T> processor) {
- return null;
+ this.responseProcessor = processor;
+ CompletableFuture<T> cf;
+ try {
+ T body = processor.onResponseBodyStart(
+ responseContentLen, responseHeaders,
+ responseFlowController); // TODO: filter headers
+ if (body != null) {
+ cf = CompletableFuture.completedFuture(body);
+ receiveDataAsync(processor);
+ } else
+ cf = receiveDataAsync(processor);
+ } catch (IOException e) {
+ cf = CompletableFuture.failedFuture(e);
+ }
+ PushGroup<?> pg = request.pushGroup();
+ if (pg != null) {
+ // if an error occurs make sure it is recorded in the PushGroup
+ cf = cf.whenComplete((t,e) -> pg.pushError(e));
+ }
+ return cf;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("streamid: ")
+ .append(streamid);
+ return sb.toString();
+ }
+
+ // pushes entire response body into response processor
+ // blocking when required by local or remote flow control
+ void receiveData() throws IOException {
+ Http2Frame frame;
+ DataFrame df = null;
+ try {
+ do {
+ frame = inputQ.take();
+ if (!(frame instanceof DataFrame)) {
+ assert false;
+ continue;
+ }
+ df = (DataFrame) frame;
+ int len = df.getDataLength();
+ ByteBuffer[] buffers = df.getData();
+ for (ByteBuffer b : buffers) {
+ responseFlowController.take();
+ responseProcessor.onResponseBodyChunk(b);
+ }
+ sendWindowUpdate(len);
+ } while (!df.getFlag(DataFrame.END_STREAM));
+ } catch (InterruptedException e) {
+ throw new IOException(e);
+ }
+ }
+
+ private <T> CompletableFuture<T> receiveDataAsync(HttpResponse.BodyProcessor<T> processor) {
+ CompletableFuture<T> cf = new CompletableFuture<>();
+ executor.execute(() -> {
+ try {
+ receiveData();
+ T body = processor.onResponseComplete();
+ cf.complete(body);
+ responseReceived();
+ } catch (Throwable t) {
+ cf.completeExceptionally(t);
+ }
+ }, null);
+ return cf;
+ }
+
+ private void sendWindowUpdate(int increment)
+ throws IOException, InterruptedException {
+ if (increment == 0)
+ return;
+ LinkedList<Http2Frame> list = new LinkedList<>();
+ WindowUpdateFrame frame = new WindowUpdateFrame();
+ frame.streamid(streamid);
+ frame.setUpdate(increment);
+ list.add(frame);
+ frame = new WindowUpdateFrame();
+ frame.streamid(0);
+ frame.setUpdate(increment);
+ list.add(frame);
+ connection.sendFrames(list);
+ }
+
+ @Override
+ CompletableFuture<Void> sendBodyAsync() {
+ final CompletableFuture<Void> cf = new CompletableFuture<>();
+ executor.execute(() -> {
+ try {
+ sendBodyImpl();
+ cf.complete(null);
+ } catch (IOException | InterruptedException e) {
+ cf.completeExceptionally(e);
+ }
+ }, null);
+ return cf;
+ }
+
+ @SuppressWarnings("unchecked")
+ Stream(HttpClientImpl client, Http2Connection connection, Exchange e) {
+ super(e);
+ this.client = client;
+ this.connection = connection;
+ this.request = e.request();
+ this.requestProcessor = request.requestProcessor();
+ responseHeaders = new HttpHeadersImpl();
+ requestHeaders = new HttpHeadersImpl();
+ rspHeadersConsumer = (name, value) -> {
+ responseHeaders.addHeader(name.toString(), value.toString());
+ };
+ this.executor = client.executorWrapper();
+ //this.response_cf = new CompletableFuture<HttpResponseImpl>();
+ this.requestPseudoHeaders = new HttpHeadersImpl();
+ // NEW
+ this.inputQ = new Queue<>();
+ }
+
+ @SuppressWarnings("unchecked")
+ Stream(HttpClientImpl client, Http2Connection connection, HttpRequestImpl req) {
+ super(null);
+ this.client = client;
+ this.connection = connection;
+ this.request = req;
+ this.requestProcessor = null;
+ responseHeaders = new HttpHeadersImpl();
+ requestHeaders = new HttpHeadersImpl();
+ rspHeadersConsumer = (name, value) -> {
+ responseHeaders.addHeader(name.toString(), value.toString());
+ };
+ this.executor = client.executorWrapper();
+ //this.response_cf = new CompletableFuture<HttpResponseImpl>();
+ this.requestPseudoHeaders = new HttpHeadersImpl();
+ // NEW
+ this.inputQ = new Queue<>();
}
- Stream(HttpClientImpl client, Http2Connection connection, Exchange e) {
- super(e);
+ /**
+ * Entry point from Http2Connection reader thread.
+ *
+ * Data frames will be removed by response body thread.
+ *
+ * @param frame
+ * @throws IOException
+ */
+ void incoming(Http2Frame frame) throws IOException, InterruptedException {
+ if ((frame instanceof HeaderFrame) && ((HeaderFrame)frame).endHeaders()) {
+ // Complete headers accumulated. handle response.
+ // It's okay if there are multiple HeaderFrames.
+ handleResponse();
+ } else if (frame instanceof DataFrame) {
+ inputQ.put(frame);
+ } else {
+ otherFrame(frame);
+ }
+ }
+
+ void otherFrame(Http2Frame frame) throws IOException {
+ switch (frame.type()) {
+ case WindowUpdateFrame.TYPE:
+ incoming_windowUpdate((WindowUpdateFrame) frame);
+ break;
+ case ResetFrame.TYPE:
+ incoming_reset((ResetFrame) frame);
+ break;
+ case PriorityFrame.TYPE:
+ incoming_priority((PriorityFrame) frame);
+ break;
+ default:
+ String msg = "Unexpected frame: " + frame.toString();
+ throw new IOException(msg);
+ }
+ }
+
+ // The Hpack decoder decodes into one of these consumers of name,value pairs
+
+ DecodingCallback rspHeadersConsumer() {
+ return rspHeadersConsumer;
+ }
+
+ // create and return the HttpResponseImpl
+ protected void handleResponse() throws IOException {
+ HttpConnection c = connection.connection; // TODO: improve
+ long statusCode = responseHeaders
+ .firstValueAsLong(":status")
+ .orElseThrow(() -> new IOException("no statuscode in response"));
+
+ this.response = new HttpResponseImpl((int)statusCode, exchange, responseHeaders, null,
+ c.sslParameters(), HttpClient.Version.HTTP_2, c);
+ this.responseContentLen = responseHeaders
+ .firstValueAsLong("content-length")
+ .orElse(-1L);
+ // different implementations for normal streams and pushed streams
+ completeResponse(response);
+ }
+
+ void incoming_reset(ResetFrame frame) {
+ // TODO: implement reset
+ int error = frame.getErrorCode();
+ IOException e = new IOException(ErrorFrame.stringForCode(error));
+ completeResponseExceptionally(e);
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ void incoming_priority(PriorityFrame frame) {
+ // TODO: implement priority
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ void incoming_windowUpdate(WindowUpdateFrame frame) {
+ int amount = frame.getUpdate();
+ if (amount > 0)
+ remoteRequestFlowController.accept(amount);
+ }
+
+ void incoming_pushPromise(HttpRequestImpl pushReq, PushedStream pushStream) throws IOException {
+ if (Log.requests()) {
+ Log.logRequest("PUSH_PROMISE: " + pushReq.toString());
+ }
+ PushGroup<?> pushGroup = request.pushGroup();
+ if (pushGroup == null) {
+ cancelImpl(new IllegalStateException("unexpected push promise"));
+ }
+ // get the handler and call it.
+ BiFunction<HttpRequest,CompletableFuture<HttpResponse>,Boolean> ph =
+ pushGroup.pushHandler();
+
+ CompletableFuture<HttpResponse> pushCF = pushStream
+ .getResponseAsync(null)
+ .thenApply(r -> (HttpResponse)r);
+ boolean accept = ph.apply(pushReq, pushCF);
+ if (!accept) {
+ IOException ex = new IOException("Stream cancelled by user");
+ cancelImpl(ex);
+ pushCF.completeExceptionally(ex);
+ } else {
+ pushStream.requestSent();
+ pushGroup.addPush();
+ }
+ }
+
+ private OutgoingHeaders headerFrame(long contentLength) {
+ HttpHeadersImpl h = request.getSystemHeaders();
+ if (contentLength > 0) {
+ h.setHeader("content-length", Long.toString(contentLength));
+ }
+ setPseudoHeaderFields();
+ OutgoingHeaders f = new OutgoingHeaders(h, request.getUserHeaders(), this);
+ if (contentLength == 0) {
+ f.setFlag(HeadersFrame.END_STREAM);
+ }
+ return f;
+ }
+
+ private void setPseudoHeaderFields() {
+ HttpHeadersImpl hdrs = requestPseudoHeaders;
+ String method = request.method();
+ hdrs.setHeader(":method", method);
+ URI uri = request.uri();
+ hdrs.setHeader(":scheme", uri.getScheme());
+ // TODO: userinfo deprecated. Needs to be removed
+ hdrs.setHeader(":authority", uri.getAuthority());
+ // TODO: ensure header names beginning with : not in user headers
+ String query = uri.getQuery();
+ String path = uri.getPath();
+ if (path == null) {
+ if (method.equalsIgnoreCase("OPTIONS")) {
+ path = "*";
+ } else {
+ path = "/";
+ }
+ }
+ if (query != null) {
+ path += "?" + query;
+ }
+ hdrs.setHeader(":path", path);
+ }
+
+ HttpHeadersImpl getRequestPseudoHeaders() {
+ return requestPseudoHeaders;
}
@Override
HttpResponseImpl getResponse() throws IOException {
- return null;
+ try {
+ return getResponseAsync(null).join();
+ } catch (Throwable e) {
+ Throwable t = e.getCause();
+ if (t instanceof IOException) {
+ throw (IOException)t;
+ }
+ throw e;
+ }
}
@Override
void sendRequest() throws IOException, InterruptedException {
+ sendHeadersOnly();
+ sendBody();
+ }
+
+ /**
+ * A simple general purpose blocking flow controller
+ */
+ class FlowController implements LongConsumer {
+ int permits;
+
+ FlowController() {
+ this.permits = 0;
+ }
+
+ @Override
+ public synchronized void accept(long n) {
+ if (n < 1) {
+ throw new InternalError("FlowController.accept called with " + n);
+ }
+ if (permits == 0) {
+ permits += n;
+ notifyAll();
+ } else {
+ permits += n;
+ }
+ }
+
+ public synchronized void take() throws InterruptedException {
+ take(1);
+ }
+
+ public synchronized void take(int amount) throws InterruptedException {
+ assert permits >= 0;
+ while (permits < amount) {
+ int n = Math.min(amount, permits);
+ permits -= n;
+ amount -= n;
+ if (amount > 0)
+ wait();
+ }
+ }
}
@Override
void sendHeadersOnly() throws IOException, InterruptedException {
+ if (Log.requests() && request != null) {
+ Log.logRequest(request.toString());
+ }
+ requestContentLen = requestProcessor.onRequestStart(request, userRequestFlowController);
+ OutgoingHeaders f = headerFrame(requestContentLen);
+ connection.sendFrame(f);
}
@Override
void sendBody() throws IOException, InterruptedException {
+ sendBodyImpl();
}
+ void registerStream(int id) {
+ this.streamid = id;
+ connection.putStream(this, streamid);
+ }
+
+ DataFrame getDataFrame() throws IOException, InterruptedException {
+ userRequestFlowController.take();
+ int maxpayloadLen = connection.getMaxSendFrameSize() - 9;
+ ByteBuffer buffer = connection.getBuffer();
+ buffer.limit(maxpayloadLen);
+ boolean complete = requestProcessor.onRequestBodyChunk(buffer);
+ buffer.flip();
+ int amount = buffer.remaining();
+ // wait for flow control if necessary. Following method will block
+ // until after headers frame is sent, so correct streamid is set.
+ remoteRequestFlowController.take(amount);
+ connection.obtainSendWindow(amount);
+
+ DataFrame df = new DataFrame();
+ df.streamid(streamid);
+ if (complete) {
+ df.setFlag(DataFrame.END_STREAM);
+ }
+ df.setData(buffer);
+ df.computeLength();
+ return df;
+ }
+
+
@Override
CompletableFuture<Void> sendHeadersAsync() {
- return null;
+ try {
+ sendHeadersOnly();
+ return CompletableFuture.completedFuture(null);
+ } catch (IOException | InterruptedException ex) {
+ return CompletableFuture.failedFuture(ex);
+ }
}
+ /**
+ * A List of responses relating to this stream. Normally there is only
+ * one response, but intermediate responses like 100 are allowed
+ * and must be passed up to higher level before continuing. Deals with races
+ * such as if responses are returned before the CFs get created by
+ * getResponseAsync()
+ */
+
+ final List<CompletableFuture<HttpResponseImpl>> response_cfs = new LinkedList<>();
+
@Override
CompletableFuture<HttpResponseImpl> getResponseAsync(Void v) {
- return null;
+ CompletableFuture<HttpResponseImpl> cf;
+ synchronized (response_cfs) {
+ if (!response_cfs.isEmpty()) {
+ cf = response_cfs.remove(0);
+ } else {
+ cf = new CompletableFuture<>();
+ response_cfs.add(cf);
+ }
+ }
+ PushGroup<?> pg = request.pushGroup();
+ if (pg != null) {
+ // if an error occurs make sure it is recorded in the PushGroup
+ cf = cf.whenComplete((t,e) -> pg.pushError(e));
+ }
+ return cf;
+ }
+
+ /**
+ * Completes the first uncompleted CF on list, and removes it. If there is no
+ * uncompleted CF then creates one (completes it) and adds to list
+ */
+ void completeResponse(HttpResponse r) {
+ HttpResponseImpl resp = (HttpResponseImpl)r;
+ synchronized (response_cfs) {
+ for (CompletableFuture<HttpResponseImpl> cf : response_cfs) {
+ if (!cf.isDone()) {
+ cf.complete(resp);
+ response_cfs.remove(cf);
+ //responseHeaders = new HttpHeadersImpl(); // for any following header blocks
+ return;
+ } else
+ System.err.println("Stream: " + this + " ALREADY DONE");
+ }
+ response_cfs.add(CompletableFuture.completedFuture(resp));
+ //responseHeaders = new HttpHeadersImpl(); // for any following header blocks
+ }
}
- @Override
- CompletableFuture<Void> sendBodyAsync() {
- return null;
+ // methods to update state and remove stream when finished
+
+ synchronized void requestSent() {
+ requestSent = true;
+ if (responseReceived)
+ connection.deleteStream(this);
+ }
+
+ synchronized void responseReceived() {
+ responseReceived = true;
+ if (requestSent)
+ connection.deleteStream(this);
+ PushGroup<?> pg = request.pushGroup();
+ if (pg != null)
+ pg.noMorePushes();
+ }
+
+ /**
+ * same as above but for errors
+ *
+ * @param t
+ */
+ void completeResponseExceptionally(Throwable t) {
+ synchronized (response_cfs) {
+ for (CompletableFuture<HttpResponseImpl> cf : response_cfs) {
+ if (!cf.isDone()) {
+ cf.completeExceptionally(t);
+ response_cfs.remove(cf);
+ return;
+ }
+ }
+ response_cfs.add(CompletableFuture.failedFuture(t));
+ }
+ }
+
+ void sendBodyImpl() throws IOException, InterruptedException {
+ if (requestContentLen == 0) {
+ // no body
+ return;
+ }
+ DataFrame df;
+ do {
+ df = getDataFrame();
+ // TODO: check accumulated content length (if not checked below)
+ connection.sendFrame(df);
+ } while (!df.getFlag(DataFrame.END_STREAM));
+ requestSent();
}
@Override
void cancel() {
+ cancelImpl(new Exception("Cancelled"));
}
+ void cancelImpl(Throwable e) {
+ Log.logTrace("cancelling stream: {0}\n", e.toString());
+ inputQ.close();
+ try {
+ connection.resetStream(streamid, ResetFrame.CANCEL);
+ } catch (IOException | InterruptedException ex) {
+ Log.logError(ex);
+ }
+ }
+
@Override
CompletableFuture<Void> sendRequestAsync() {
- return null;
+ CompletableFuture<Void> cf = new CompletableFuture<>();
+ executor.execute(() -> {
+ try {
+ sendRequest();
+ cf.complete(null);
+ } catch (IOException |InterruptedException e) {
+ cf.completeExceptionally(e);
+ }
+ }, null);
+ return cf;
}
@Override
<T> T responseBody(HttpResponse.BodyProcessor<T> processor) throws IOException {
- return null;
+ this.responseProcessor = processor;
+ T body = processor.onResponseBodyStart(
+ responseContentLen, responseHeaders,
+ responseFlowController); // TODO: filter headers
+ if (body == null) {
+ receiveData();
+ return processor.onResponseComplete();
+ } else
+ receiveDataAsync(processor);
+ responseReceived();
+ return body;
+ }
+
+ // called from Http2Connection reader thread
+ synchronized void updateOutgoingWindow(int update) {
+ remoteRequestFlowController.accept(update);
+ }
+
+ void close(String msg) {
+ cancel();
+ }
+
+ static class PushedStream extends Stream {
+ final PushGroup<?> pushGroup;
+ final private Stream parent; // used by server push streams
+ // push streams need the response CF allocated up front as it is
+ // given directly to user via the multi handler callback function.
+ final CompletableFuture<HttpResponseImpl> pushCF;
+ final HttpRequestImpl pushReq;
+
+ PushedStream(PushGroup<?> pushGroup, HttpClientImpl client,
+ Http2Connection connection, Stream parent,
+ HttpRequestImpl pushReq) {
+ super(client, connection, pushReq);
+ this.pushGroup = pushGroup;
+ this.pushReq = pushReq;
+ this.pushCF = new CompletableFuture<>();
+ this.parent = parent;
+ }
+
+ // Following methods call the super class but in case of
+ // error record it in the PushGroup. The error method is called
+ // with a null value when no error occurred (is a no-op)
+ @Override
+ CompletableFuture<Void> sendBodyAsync() {
+ return super.sendBodyAsync()
+ .whenComplete((v, t) -> pushGroup.pushError(t));
+ }
+
+ @Override
+ CompletableFuture<Void> sendHeadersAsync() {
+ return super.sendHeadersAsync()
+ .whenComplete((v, t) -> pushGroup.pushError(t));
+ }
+
+ @Override
+ CompletableFuture<Void> sendRequestAsync() {
+ return super.sendRequestAsync()
+ .whenComplete((v, t) -> pushGroup.pushError(t));
+ }
+
+ @Override
+ CompletableFuture<HttpResponseImpl> getResponseAsync(Void vo) {
+ return pushCF.whenComplete((v, t) -> pushGroup.pushError(t));
+ }
+
+ @Override
+ <T> CompletableFuture<T> responseBodyAsync(HttpResponse.BodyProcessor<T> processor) {
+ return super.responseBodyAsync(processor)
+ .whenComplete((v, t) -> pushGroup.pushError(t));
+ }
+
+ @Override
+ void completeResponse(HttpResponse r) {
+ HttpResponseImpl resp = (HttpResponseImpl)r;
+ Utils.logResponse(resp);
+ pushCF.complete(resp);
+ }
+
+ @Override
+ void completeResponseExceptionally(Throwable t) {
+ pushCF.completeExceptionally(t);
+ }
+
+ @Override
+ synchronized void responseReceived() {
+ super.responseReceived();
+ pushGroup.pushCompleted();
+ }
+
+ // create and return the PushResponseImpl
+ @Override
+ protected void handleResponse() {
+ HttpConnection c = connection.connection; // TODO: improve
+ long statusCode = responseHeaders
+ .firstValueAsLong(":status")
+ .orElse(-1L);
+
+ if (statusCode == -1L)
+ completeResponseExceptionally(new IOException("No status code"));
+ ImmutableHeaders h = new ImmutableHeaders(responseHeaders, Utils.ALL_HEADERS);
+ this.response = new HttpResponseImpl((int)statusCode, pushReq, h, this,
+ c.sslParameters());
+ this.responseContentLen = responseHeaders
+ .firstValueAsLong("content-length")
+ .orElse(-1L);
+ // different implementations for normal streams and pushed streams
+ completeResponse(response);
+ }
+ }
+
+ /**
+ * One PushGroup object is associated with the parent Stream of
+ * the pushed Streams. This keeps track of all common state associated
+ * with the pushes.
+ */
+ static class PushGroup<T> {
+ // the overall completion object, completed when all pushes are done.
+ final CompletableFuture<T> resultCF;
+ Throwable error; // any exception that occured during pushes
+
+ // CF for main response
+ final CompletableFuture<HttpResponse> mainResponse;
+
+ // user's processor object
+ final HttpResponse.MultiProcessor<T> multiProcessor;
+
+ // per push handler function provided by processor
+ final private BiFunction<HttpRequest,
+ CompletableFuture<HttpResponse>,
+ Boolean> pushHandler;
+ int numberOfPushes;
+ int remainingPushes;
+ boolean noMorePushes = false;
+
+ PushGroup(HttpResponse.MultiProcessor<T> multiProcessor, HttpRequestImpl req) {
+ this.resultCF = new CompletableFuture<>();
+ this.mainResponse = new CompletableFuture<>();
+ this.multiProcessor = multiProcessor;
+ this.pushHandler = multiProcessor.onStart(req, mainResponse);
+ }
+
+ CompletableFuture<T> groupResult() {
+ return resultCF;
+ }
+
+ CompletableFuture<HttpResponse> mainResponse() {
+ return mainResponse;
+ }
+
+ private BiFunction<HttpRequest,
+ CompletableFuture<HttpResponse>, Boolean> pushHandler()
+ {
+ return pushHandler;
+ }
+
+ synchronized void addPush() {
+ numberOfPushes++;
+ remainingPushes++;
+ }
+
+ synchronized int numberOfPushes() {
+ return numberOfPushes;
+ }
+ // This is called when the main body response completes because it means
+ // no more PUSH_PROMISEs are possible
+ synchronized void noMorePushes() {
+ noMorePushes = true;
+ checkIfCompleted();
+ }
+
+ synchronized void pushCompleted() {
+ remainingPushes--;
+ checkIfCompleted();
+ }
+
+ synchronized void checkIfCompleted() {
+ if (remainingPushes == 0 && error == null && noMorePushes) {
+ T overallResult = multiProcessor.onComplete();
+ resultCF.complete(overallResult);
+ }
+ }
+
+ synchronized void pushError(Throwable t) {
+ if (t == null)
+ return;
+ this.error = t;
+ resultCF.completeExceptionally(t);
+ }
}
}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java Fri May 06 06:23:30 2016 -0700
@@ -21,28 +21,37 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
*/
-
package java.net.http;
+import sun.net.NetProperties;
+
+import javax.net.ssl.SSLParameters;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
+import java.net.InetSocketAddress;
import java.net.NetPermission;
import java.net.URI;
import java.net.URLPermission;
+import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.net.ssl.SSLParameters;
-import sun.net.NetProperties;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.LongBinaryOperator;
+import java.util.function.Predicate;
/**
* Miscellaneous utilities
*/
-class Utils {
+final class Utils {
/**
* Allocated buffer size. Must never be higher than 16K. But can be lower
@@ -51,7 +60,59 @@
*/
public static final int BUFSIZE = 16 * 1024;
- /** Validates a RFC7230 token */
+ private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
+ "authorization", "connection", "cookie", "content-length",
+ "date", "expect", "from", "host", "origin", "proxy-authorization",
+ "referer", "user-agent", "upgrade", "via", "warning");
+
+ static final Predicate<String>
+ ALLOWED_HEADERS = header -> !Utils.DISALLOWED_HEADERS_SET.contains(header);
+
+ static final Predicate<String>
+ ALL_HEADERS = header -> true;
+
+ static InetSocketAddress getAddress(HttpRequestImpl req) {
+ URI uri = req.uri();
+ if (uri == null) {
+ return req.authority();
+ }
+ int port = uri.getPort();
+ if (port == -1) {
+ if (uri.getScheme().equalsIgnoreCase("https")) {
+ port = 443;
+ } else {
+ port = 80;
+ }
+ }
+ String host = uri.getHost();
+ if (req.proxy() == null) {
+ return new InetSocketAddress(host, port);
+ } else {
+ return InetSocketAddress.createUnresolved(host, port);
+ }
+ }
+
+ /**
+ * Puts position to limit and limit to capacity so we can resume reading
+ * into this buffer, but if required > 0 then limit may be reduced so that
+ * no more than required bytes are read next time.
+ */
+ static void resumeChannelRead(ByteBuffer buf, int required) {
+ int limit = buf.limit();
+ buf.position(limit);
+ int capacity = buf.capacity() - limit;
+ if (required > 0 && required < capacity) {
+ buf.limit(limit + required);
+ } else {
+ buf.limit(buf.capacity());
+ }
+ }
+
+ private Utils() { }
+
+ /**
+ * Validates a RFC7230 token
+ */
static void validateToken(String token, String errormsg) {
int length = token.length();
for (int i = 0; i < length; i++) {
@@ -69,7 +130,7 @@
}
/**
- * Return sthe security permission required for the given details.
+ * Returns the security permission required for the given details.
* If method is CONNECT, then uri must be of form "scheme://host:port"
*/
static URLPermission getPermission(URI uri,
@@ -85,7 +146,7 @@
} else {
sb.append(uri.getScheme())
.append("://")
- .append(uri.getHost())
+ .append(uri.getAuthority())
.append(uri.getPath());
urlstring = sb.toString();
@@ -117,13 +178,13 @@
}
static int getIntegerNetProperty(String name, int defaultValue) {
- return AccessController.doPrivileged((PrivilegedAction<Integer>)() ->
- NetProperties.getInteger(name, defaultValue) );
+ return AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
+ NetProperties.getInteger(name, defaultValue));
}
static String getNetProperty(String name) {
- return AccessController.doPrivileged((PrivilegedAction<String>)() ->
- NetProperties.get(name) );
+ return AccessController.doPrivileged((PrivilegedAction<String>) () ->
+ NetProperties.get(name));
}
static SSLParameters copySSLParameters(SSLParameters p) {
@@ -134,7 +195,9 @@
p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm());
p1.setMaximumPacketSize(p.getMaximumPacketSize());
p1.setNeedClientAuth(p.getNeedClientAuth());
- p1.setProtocols(p.getProtocols().clone());
+ String[] protocols = p.getProtocols();
+ if (protocols != null)
+ p1.setProtocols(protocols.clone());
p1.setSNIMatchers(p.getSNIMatchers());
p1.setServerNames(p.getServerNames());
p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder());
@@ -142,33 +205,14 @@
return p1;
}
-
- /** Resumes reading into the given buffer. */
- static void unflip(ByteBuffer buf) {
- buf.position(buf.limit());
- buf.limit(buf.capacity());
- }
-
/**
* Set limit to position, and position to mark.
- *
- *
- * @param buffer
- * @param mark
*/
static void flipToMark(ByteBuffer buffer, int mark) {
buffer.limit(buffer.position());
buffer.position(mark);
}
- /** Compact and leave ready for reading. */
- static void compact(List<ByteBuffer> buffers) {
- for (ByteBuffer b : buffers) {
- b.compact();
- b.flip();
- }
- }
-
static String stackTrace(Throwable t) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
String s = null;
@@ -182,8 +226,10 @@
return s;
}
- /** Copies as much of src to dst as possible. */
- static void copy (ByteBuffer src, ByteBuffer dst) {
+ /**
+ * Copies as much of src to dst as possible.
+ */
+ static void copy(ByteBuffer src, ByteBuffer dst) {
int srcLen = src.remaining();
int dstLen = dst.remaining();
if (srcLen > dstLen) {
@@ -204,18 +250,101 @@
return dst;
}
- static String combine(String[] s) {
+ //
+ // Helps to trim long names (packages, nested/inner types) in logs/toString
+ //
+ static String toStringSimple(Object o) {
+ return o.getClass().getSimpleName() + "@" +
+ Integer.toHexString(System.identityHashCode(o));
+ }
+
+ //
+ // 1. It adds a number of remaining bytes;
+ // 2. Standard Buffer-type toString for CharBuffer (since it adheres to the
+ // contract of java.lang.CharSequence.toString() which is both not too
+ // useful and not too private)
+ //
+ static String toString(Buffer b) {
+ return toStringSimple(b)
+ + "[pos=" + b.position()
+ + " lim=" + b.limit()
+ + " cap=" + b.capacity()
+ + " rem=" + b.remaining() + "]";
+ }
+
+ static String toString(CharSequence s) {
+ return s == null
+ ? "null"
+ : toStringSimple(s) + "[len=" + s.length() + "]";
+ }
+
+ static String dump(Object... objects) {
+ return Arrays.toString(objects);
+ }
+
+ static final System.Logger logger = System.getLogger("java.net.http.WebSocket");
+
+ static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
+
+ static String webSocketSpecViolation(String section, String detail) {
+ return "RFC 6455 " + section + " " + detail;
+ }
+
+ static void logResponse(HttpResponseImpl r) {
+ if (!Log.requests()) {
+ return;
+ }
StringBuilder sb = new StringBuilder();
- sb.append('[');
- boolean first = true;
- for (String s1 : s) {
- if (!first) {
- sb.append(", ");
- first = false;
+ String method = r.request().method();
+ URI uri = r.uri();
+ String uristring = uri == null ? "" : uri.toString();
+ sb.append('(').append(method).append(" ").append(uristring).append(") ").append(Integer.toString(r.statusCode()));
+ Log.logResponse(sb.toString());
+ }
+
+ static int remaining(ByteBuffer[] bufs) {
+ int remain = 0;
+ for (ByteBuffer buf : bufs)
+ remain += buf.remaining();
+ return remain;
+ }
+
+ // assumes buffer was written into starting at position zero
+ static void unflip(ByteBuffer buf) {
+ buf.position(buf.limit());
+ buf.limit(buf.capacity());
+ }
+
+ static void close(Closeable... chans) {
+ for (Closeable chan : chans) {
+ System.err.println("Closing " + chan);
+ try {
+ chan.close();
+ } catch (IOException e) {
}
- sb.append(s1);
}
- sb.append(']');
- return sb.toString();
+ }
+
+ static ByteBuffer[] reduce(ByteBuffer[] bufs, int start, int number) {
+ if (start == 0 && number == bufs.length)
+ return bufs;
+ ByteBuffer[] nbufs = new ByteBuffer[number];
+ int j = 0;
+ for (int i=start; i<start+number; i++)
+ nbufs[j++] = bufs[i];
+ return nbufs;
}
+
+ static String asString(ByteBuffer buf) {
+ byte[] b = new byte[buf.remaining()];
+ buf.get(b);
+ return new String(b, StandardCharsets.US_ASCII);
+ }
+
+ // Put all these static 'empty' singletons here
+ @SuppressWarnings("rawtypes")
+ static CompletableFuture[] EMPTY_CFARRAY = new CompletableFuture[0];
+
+ static ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
+ static ByteBuffer[] EMPTY_BB_ARRAY = new ByteBuffer[0];
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WindowUpdateFrame.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,78 @@
+/*
+ * 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
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class WindowUpdateFrame extends Http2Frame {
+
+ int windowUpdate;
+
+ WindowUpdateFrame() {
+ type = TYPE;
+ }
+
+ public final static int TYPE = 0x8;
+
+ public void setUpdate(int windowUpdate) {
+ this.windowUpdate = windowUpdate;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(super.toString())
+ .append(" WindowUpdate: ")
+ .append(windowUpdate);
+ return sb.toString();
+ }
+
+ public int getUpdate() {
+ return this.windowUpdate;
+ }
+
+ /**
+ */
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ if (length != 4) {
+ throw new IOException("Invalid WindowUpdate frame");
+ }
+ windowUpdate = bc.getInt() & 0x7fffffff;
+ }
+
+ @Override
+ void computeLength() {
+ length = 4;
+ }
+
+ @Override
+ void writeOutgoing(ByteBufferGenerator bg) {
+ super.writeOutgoing(bg);
+ ByteBuffer buf = bg.getBuffer(4);
+ buf.putInt(windowUpdate);
+ }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java Fri May 06 06:23:30 2016 -0700
@@ -24,11 +24,11 @@
*/
/**
- * <h2>High level HTTP API</h2>
- * This provides a high-level client interface to HTTP (versions 1.1 and 2).
- * Synchronous and asynchronous (via
- * {@link java.util.concurrent.CompletableFuture}) modes are provided. The main
- * classes defined are:
+ * <h2>High level HTTP and WebSocket API</h2>
+ * This provides a high-level client interfaces to HTTP (versions 1.1 and 2)
+ * and WebSocket. Synchronous and asynchronous (via {@link
+ * java.util.concurrent.CompletableFuture}) modes are provided for HTTP.
+ * WebSocket works in asynchronous mode only. The main types defined are:
* <ul>
* <li>{@link java.net.http.HttpClient}</li>
* <li>{@link java.net.http.HttpRequest}</li>
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java Fri May 06 06:23:30 2016 -0700
@@ -231,13 +231,15 @@
cname = System.getProperty("java.util.logging.manager");
if (cname != null) {
try {
- Class<?> clz = ClassLoader.getSystemClassLoader()
- .loadClass(cname);
- mgr = (LogManager) clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = ClassLoader.getSystemClassLoader()
+ .loadClass(cname).newInstance();
+ mgr = (LogManager) tmp;
} catch (ClassNotFoundException ex) {
- Class<?> clz = Thread.currentThread()
- .getContextClassLoader().loadClass(cname);
- mgr = (LogManager) clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Thread.currentThread()
+ .getContextClassLoader().loadClass(cname).newInstance();
+ mgr = (LogManager) tmp;
}
}
} catch (Exception ex) {
@@ -991,8 +993,9 @@
List<Handler> handlers = new ArrayList<>(names.length);
for (String type : names) {
try {
- Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
- Handler hdl = (Handler) clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = ClassLoader.getSystemClassLoader().loadClass(type).newInstance();
+ Handler hdl = (Handler) o;
// Check if there is a property defining the
// this handler's level.
String levs = getProperty(type + ".level");
@@ -1330,11 +1333,13 @@
// calling readConfiguration(InputStream) with a suitable stream.
try {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
- clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object witness = clz.newInstance();
return;
} catch (ClassNotFoundException ex) {
Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
- clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object witness = clz.newInstance();
return;
}
} catch (Exception ex) {
@@ -1561,7 +1566,8 @@
for (String word : names) {
try {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
- clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object witness = clz.newInstance();
} catch (Exception ex) {
System.err.println("Can't load config class \"" + word + "\"");
System.err.println("" + ex);
@@ -2307,8 +2313,9 @@
String val = getProperty(name);
try {
if (val != null) {
- Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val);
- return (Filter) clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = ClassLoader.getSystemClassLoader().loadClass(val).newInstance();
+ return (Filter) o;
}
} catch (Exception ex) {
// We got one of a variety of exceptions in creating the
@@ -2328,8 +2335,9 @@
String val = getProperty(name);
try {
if (val != null) {
- Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(val);
- return (Formatter) clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = ClassLoader.getSystemClassLoader().loadClass(val).newInstance();
+ return (Formatter) o;
}
} catch (Exception ex) {
// We got one of a variety of exceptions in creating the
--- a/jdk/src/java.logging/share/classes/java/util/logging/MemoryHandler.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.logging/share/classes/java/util/logging/MemoryHandler.java Fri May 06 06:23:30 2016 -0700
@@ -117,7 +117,9 @@
Class<?> clz;
try {
clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
- target = (Handler) clz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = clz.newInstance();
+ target = (Handler) o;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e);
}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Fri May 06 06:23:30 2016 -0700
@@ -655,7 +655,9 @@
final Object[] openArray = (Object[]) openValue;
final Collection<Object> valueCollection;
try {
- valueCollection = cast(collectionClass.newInstance());
+ @SuppressWarnings("deprecation")
+ Collection<?> tmp = collectionClass.newInstance();
+ valueCollection = cast(tmp);
} catch (Exception e) {
throw invalidObjectException("Cannot create collection", e);
}
@@ -1114,7 +1116,9 @@
try {
final Class<?> targetClass = getTargetClass();
ReflectUtil.checkPackageAccess(targetClass);
- o = targetClass.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = targetClass.newInstance();
+ o = tmp;
for (int i = 0; i < itemNames.length; i++) {
if (cd.containsKey(itemNames[i])) {
Object openItem = cd.get(itemNames[i]);
--- a/jdk/src/java.management/share/classes/javax/management/MBeanServerFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.management/share/classes/javax/management/MBeanServerFactory.java Fri May 06 06:23:30 2016 -0700
@@ -458,6 +458,7 @@
**/
private static MBeanServerBuilder newBuilder(Class<?> builderClass) {
try {
+ @SuppressWarnings("deprecation")
final Object abuilder = builderClass.newInstance();
return (MBeanServerBuilder)abuilder;
} catch (RuntimeException x) {
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java Fri May 06 06:23:30 2016 -0700
@@ -531,7 +531,9 @@
// We have just proved that this cast is correct
Class<? extends T> providerClassT = Util.cast(providerClass);
try {
- return providerClassT.newInstance();
+ @SuppressWarnings("deprecation")
+ T result = providerClassT.newInstance();
+ return result;
} catch (Exception e) {
final String msg =
"Exception when instantiating provider [" + className +
--- a/jdk/src/java.naming/share/classes/com/sun/naming/internal/FactoryEnumeration.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.naming/share/classes/com/sun/naming/internal/FactoryEnumeration.java Fri May 06 06:23:30 2016 -0700
@@ -86,7 +86,9 @@
answer = cls;
}
// Instantiate Class to get factory
- answer = ((Class) answer).newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = ((Class) answer).newInstance();
+ answer = tmp;
ref = new NamedWeakReference<>(answer, className);
factories.set(posn-1, ref); // replace Class object or null
return answer;
--- a/jdk/src/java.naming/share/classes/com/sun/naming/internal/ResourceManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.naming/share/classes/com/sun/naming/internal/ResourceManager.java Fri May 06 06:23:30 2016 -0700
@@ -399,7 +399,9 @@
className = parser.nextToken() + classSuffix;
try {
// System.out.println("loading " + className);
- factory = helper.loadClass(className, loader).newInstance();
+ @SuppressWarnings("deprecation") // Class.newInstance
+ Object tmp = helper.loadClass(className, loader).newInstance();
+ factory = tmp;
} catch (InstantiationException e) {
NamingException ne =
new NamingException("Cannot instantiate " + className);
--- a/jdk/src/java.naming/share/classes/javax/naming/ldap/StartTlsRequest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.naming/share/classes/javax/naming/ldap/StartTlsRequest.java Fri May 06 06:23:30 2016 -0700
@@ -192,18 +192,12 @@
}
try {
VersionHelper helper = VersionHelper.getVersionHelper();
- Class<?> clas = helper.loadClass(
- "com.sun.jndi.ldap.ext.StartTlsResponseImpl");
-
- resp = (StartTlsResponse) clas.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = helper.loadClass(
+ "com.sun.jndi.ldap.ext.StartTlsResponseImpl").newInstance();
+ resp = (StartTlsResponse) o;
- } catch (IllegalAccessException e) {
- throw wrapException(e);
-
- } catch (InstantiationException e) {
- throw wrapException(e);
-
- } catch (ClassNotFoundException e) {
+ } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
throw wrapException(e);
}
--- a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java Fri May 06 06:23:30 2016 -0700
@@ -159,7 +159,9 @@
}
}
- return (clas != null) ? (ObjectFactory) clas.newInstance() : null;
+ @SuppressWarnings("deprecation") // Class.newInstance
+ ObjectFactory result = (clas != null) ? (ObjectFactory) clas.newInstance() : null;
+ return result;
}
@@ -710,8 +712,9 @@
if (factory == null) {
try {
- factory = (InitialContextFactory)
- helper.loadClass(className).newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = helper.loadClass(className).newInstance();
+ factory = (InitialContextFactory) o;
} catch (Exception e) {
NoInitialContextException ne =
new NoInitialContextException(
--- a/jdk/src/java.prefs/share/classes/java/util/prefs/Preferences.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.prefs/share/classes/java/util/prefs/Preferences.java Fri May 06 06:23:30 2016 -0700
@@ -238,10 +238,11 @@
// dependent on the invoking thread.
// Checking AllPermission also seems wrong.
try {
- return (PreferencesFactory)
- Class.forName(factoryName, false,
- ClassLoader.getSystemClassLoader())
+ @SuppressWarnings("deprecation")
+ Object result =Class.forName(factoryName, false,
+ ClassLoader.getSystemClassLoader())
.newInstance();
+ return (PreferencesFactory)result;
} catch (Exception ex) {
try {
// workaround for javaws, plugin,
@@ -250,11 +251,12 @@
if (sm != null) {
sm.checkPermission(new java.security.AllPermission());
}
- return (PreferencesFactory)
- Class.forName(factoryName, false,
- Thread.currentThread()
- .getContextClassLoader())
+ @SuppressWarnings("deprecation")
+ Object result = Class.forName(factoryName, false,
+ Thread.currentThread()
+ .getContextClassLoader())
.newInstance();
+ return (PreferencesFactory) result;
} catch (Exception e) {
throw new InternalError(
"Can't instantiate Preferences factory "
@@ -299,9 +301,10 @@
platformFactory = "java.util.prefs.FileSystemPreferencesFactory";
}
try {
- return (PreferencesFactory)
- Class.forName(platformFactory, false,
- Preferences.class.getClassLoader()).newInstance();
+ @SuppressWarnings("deprecation")
+ Object result = Class.forName(platformFactory, false,
+ Preferences.class.getClassLoader()).newInstance();
+ return (PreferencesFactory) result;
} catch (Exception e) {
throw new InternalError(
"Can't instantiate platform default Preferences factory "
--- a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java Fri May 06 06:23:30 2016 -0700
@@ -272,6 +272,7 @@
Class<? extends RemoteRef> refClass =
Class.forName(RemoteRef.packagePrefix + "." + in.readUTF())
.asSubclass(RemoteRef.class);
+ @SuppressWarnings("deprecation")
RemoteRef ref = refClass.newInstance();
ref.readExternal(in);
activator = (Activator)
--- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java Fri May 06 06:23:30 2016 -0700
@@ -681,7 +681,9 @@
Class.forName(providerClassName, false,
ClassLoader.getSystemClassLoader())
.asSubclass(RMIClassLoaderSpi.class);
- return providerClass.newInstance();
+ @SuppressWarnings("deprecation")
+ RMIClassLoaderSpi result = providerClass.newInstance();
+ return result;
} catch (ClassNotFoundException e) {
throw new NoClassDefFoundError(e.getMessage());
--- a/jdk/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java Fri May 06 06:23:30 2016 -0700
@@ -439,18 +439,16 @@
RemoteRef.packagePrefix + "." + refClassName;
Class<?> refClass = Class.forName(internalRefClassName);
try {
- ref = (RemoteRef) refClass.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = refClass.newInstance();
+ ref = (RemoteRef) tmp;
/*
* If this step fails, assume we found an internal
* class that is not meant to be a serializable ref
* type.
*/
- } catch (InstantiationException e) {
- throw new ClassNotFoundException(internalRefClassName, e);
- } catch (IllegalAccessException e) {
- throw new ClassNotFoundException(internalRefClassName, e);
- } catch (ClassCastException e) {
+ } catch (InstantiationException | IllegalAccessException | ClassCastException e) {
throw new ClassNotFoundException(internalRefClassName, e);
}
ref.readExternal(in);
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Fri May 06 06:23:30 2016 -0700
@@ -2066,7 +2066,9 @@
try {
Class<?> execPolicyClass = getRMIClass(execPolicyClassName);
- execPolicy = execPolicyClass.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = execPolicyClass.newInstance();
+ execPolicy = tmp;
execPolicyMethod =
execPolicyClass.getMethod("checkExecCommand",
ActivationGroupDesc.class,
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java Fri May 06 06:23:30 2016 -0700
@@ -111,8 +111,9 @@
type = "PC/SC";
Provider sun = Security.getProvider("SunPCSC");
if (sun == null) {
- Class<?> clazz = Class.forName("sun.security.smartcardio.SunPCSC");
- sun = (Provider)clazz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName("sun.security.smartcardio.SunPCSC").newInstance();
+ sun = (Provider)o;
}
factory = TerminalFactory.getInstance(type, null, sun);
} catch (Exception e) {
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java Fri May 06 06:23:30 2016 -0700
@@ -2962,7 +2962,9 @@
SQLData obj = null;
try {
ReflectUtil.checkPackageAccess(c);
- obj = (SQLData) c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ obj = (SQLData) tmp;
} catch(Exception ex) {
throw new SQLException("Unable to Instantiate: ", ex);
}
@@ -5710,7 +5712,9 @@
SQLData obj = null;
try {
ReflectUtil.checkPackageAccess(c);
- obj = (SQLData) c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ obj = (SQLData) tmp;
} catch(Exception ex) {
throw new SQLException("Unable to Instantiate: ", ex);
}
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Fri May 06 06:23:30 2016 -0700
@@ -574,7 +574,9 @@
SQLData obj = null;
try {
ReflectUtil.checkPackageAccess(c);
- obj = (SQLData)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ obj = (SQLData)tmp;
} catch (Exception ex) {
throw new SQLException("Unable to Instantiate: ", ex);
}
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java Fri May 06 06:23:30 2016 -0700
@@ -136,8 +136,9 @@
}
// getFactoryClass takes care of adding the read edge if
// necessary
- Class<?> c = getFactoryClass(factoryClassName, null, false);
- factory = (RowSetFactory) c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = getFactoryClass(factoryClassName, null, false).newInstance();
+ factory = (RowSetFactory) o;
}
} catch (Exception e) {
throw new SQLException( "RowSetFactory: " + factoryClassName +
@@ -202,6 +203,7 @@
// getFactoryClass takes care of adding the read edge if
// necessary
Class<?> providerClass = getFactoryClass(factoryClassName, cl, false);
+ @SuppressWarnings("deprecation")
RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
if (debug) {
trace("Created new instance of " + providerClass +
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java Fri May 06 06:23:30 2016 -0700
@@ -478,7 +478,9 @@
SQLData obj = null;
try {
ReflectUtil.checkPackageAccess(c);
- obj = (SQLData)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ obj = (SQLData)tmp;
} catch (Exception ex) {
throw new SQLException("Unable to Instantiate: ", ex);
}
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java Fri May 06 06:23:30 2016 -0700
@@ -582,14 +582,12 @@
* there.
**/
c = Class.forName(providerID, true, cl);
- return (SyncProvider) c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object result = c.newInstance();
+ return (SyncProvider)result;
- } catch (IllegalAccessException e) {
+ } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
throw new SyncFactoryException("IllegalAccessException: " + e.getMessage());
- } catch (InstantiationException e) {
- throw new SyncFactoryException("InstantiationException: " + e.getMessage());
- } catch (ClassNotFoundException e) {
- throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage());
}
}
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java Fri May 06 06:23:30 2016 -0700
@@ -152,7 +152,9 @@
log.log(java.util.logging.Level.FINE, "Create URI \"" + algorithmURI + "\" class \""
+ implementingClass + "\"");
}
- return implementingClass.newInstance();
+ @SuppressWarnings("deprecation")
+ SignatureAlgorithmSpi result = implementingClass.newInstance();
+ return result;
} catch (IllegalAccessException ex) {
Object exArgs[] = { algorithmURI, ex.getMessage() };
throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex);
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java Fri May 06 06:23:30 2016 -0700
@@ -115,7 +115,9 @@
Class<? extends CanonicalizerSpi> implementingClass =
canonicalizerHash.get(algorithmURI);
- canonicalizerSpi = implementingClass.newInstance();
+ @SuppressWarnings("deprecation")
+ CanonicalizerSpi tmp = implementingClass.newInstance();
+ canonicalizerSpi = tmp;
canonicalizerSpi.reset = true;
} catch (Exception e) {
Object exArgs[] = { algorithmURI };
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java Fri May 06 06:23:30 2016 -0700
@@ -182,6 +182,7 @@
public static void register(String className, boolean globalResolver)
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
JavaUtils.checkRegisterPermission();
+ @SuppressWarnings("deprecation")
KeyResolverSpi keyResolverSpi =
(KeyResolverSpi) Class.forName(className).newInstance();
keyResolverSpi.setGlobalResolver(globalResolver);
@@ -207,7 +208,9 @@
KeyResolverSpi keyResolverSpi = null;
Exception ex = null;
try {
- keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = Class.forName(className).newInstance();
+ keyResolverSpi = (KeyResolverSpi) tmp;
} catch (ClassNotFoundException e) {
ex = e;
} catch (IllegalAccessException e) {
@@ -272,6 +275,7 @@
JavaUtils.checkRegisterPermission();
List<KeyResolver> keyResolverList = new ArrayList<KeyResolver>(classNames.size());
for (String className : classNames) {
+ @SuppressWarnings("deprecation")
KeyResolverSpi keyResolverSpi =
(KeyResolverSpi) Class.forName(className).newInstance();
keyResolverSpi.setGlobalResolver(false);
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java Fri May 06 06:23:30 2016 -0700
@@ -110,7 +110,9 @@
KeyResolverSpi tmp = this;
if (globalResolver) {
try {
- tmp = getClass().newInstance();
+ @SuppressWarnings("deprecation")
+ KeyResolverSpi krs = getClass().newInstance();
+ tmp = krs;
} catch (InstantiationException e) {
throw new KeyResolverException("", e);
} catch (IllegalAccessException e) {
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java Fri May 06 06:23:30 2016 -0700
@@ -160,7 +160,9 @@
throw new InvalidTransformException("signature.Transform.UnknownTransform", exArgs);
}
try {
- transformSpi = transformSpiClass.newInstance();
+ @SuppressWarnings("deprecation")
+ TransformSpi tmp = transformSpiClass.newInstance();
+ transformSpi = tmp;
} catch (InstantiationException ex) {
Object exArgs[] = { algorithmURI };
throw new InvalidTransformException(
@@ -345,7 +347,9 @@
}
TransformSpi newTransformSpi = null;
try {
- newTransformSpi = transformSpiClass.newInstance();
+ @SuppressWarnings("deprecation")
+ TransformSpi tmp = transformSpiClass.newInstance();
+ newTransformSpi = tmp;
} catch (InstantiationException ex) {
Object exArgs[] = { algorithmURI };
throw new InvalidTransformException(
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java Fri May 06 06:23:30 2016 -0700
@@ -99,8 +99,10 @@
ResourceResolver resolverTmp = resolver;
if (!resolver.resolverSpi.engineIsThreadSafe()) {
try {
- resolverTmp =
- new ResourceResolver(resolver.resolverSpi.getClass().newInstance());
+ @SuppressWarnings("deprecation")
+ ResourceResolver tmp = new ResourceResolver(resolver.resolverSpi.getClass().newInstance());
+ resolverTmp = tmp;
+ ;
} catch (InstantiationException e) {
throw new ResourceResolverException("", e, context.attr, context.baseUri);
} catch (IllegalAccessException e) {
@@ -246,6 +248,7 @@
public static void register(Class<? extends ResourceResolverSpi> className, boolean start) {
JavaUtils.checkRegisterPermission();
try {
+ @SuppressWarnings("deprecation")
ResourceResolverSpi resourceResolverSpi = className.newInstance();
register(resourceResolverSpi, start);
} catch (IllegalAccessException e) {
--- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java Fri May 06 06:23:30 2016 -0700
@@ -121,6 +121,7 @@
Class<?> translatorClass = getTranslatorClass(o.getClass());
if (translatorClass != null) {
try {
+ @SuppressWarnings("deprecation")
Translator t = (Translator)translatorClass.newInstance();
t.setSource(o);
a = t;
--- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java Fri May 06 06:23:30 2016 -0700
@@ -148,6 +148,7 @@
true,
this.getClass().getClassLoader());
+ @SuppressWarnings("deprecation")
Charset cs = (Charset)c.newInstance();
cache.put(csn, new SoftReference<Charset>(cs));
return cs;
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Util.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Util.java Fri May 06 06:23:30 2016 -0700
@@ -88,8 +88,9 @@
p = Security.getProvider(providerName);
if (p == null) {
try {
- Class<?> clazz = Class.forName(className);
- p = (Provider)clazz.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName(className).newInstance();
+ p = (Provider)o;
} catch (Exception e) {
throw new ProviderException
("Could not find provider " + providerName, e);
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java Fri May 06 06:23:30 2016 -0700
@@ -1446,7 +1446,9 @@
}
return null;
}
- return (CallbackHandler)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object result = c.newInstance();
+ return (CallbackHandler)result;
}
});
// save it
--- a/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Fri May 06 06:23:30 2016 -0700
@@ -89,9 +89,10 @@
if (cn == null)
return false;
try {
- Class<?> c = Class.forName(cn, true,
- ClassLoader.getSystemClassLoader());
- provider = (HttpServerProvider)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Class.forName(cn, true,
+ ClassLoader.getSystemClassLoader()).newInstance();
+ provider = (HttpServerProvider)o;
return true;
} catch (ClassNotFoundException |
IllegalAccessException |
--- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java Fri May 06 06:23:30 2016 -0700
@@ -82,7 +82,9 @@
}
else {
try {
- t = (Terminal) Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
+ t = (Terminal) o;
}
catch (Exception e) {
throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e);
--- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java Fri May 06 06:23:30 2016 -0700
@@ -61,6 +61,7 @@
List<Completer> completorList = new ArrayList<Completer>();
for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) {
+ @SuppressWarnings("deprecation")
Object obj = Class.forName(tok.nextToken()).newInstance();
completorList.add((Completer) obj);
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java Fri May 06 06:23:30 2016 -0700
@@ -136,10 +136,10 @@
jartool.moduleVersion = Version.parse(arg);
}
},
- new Option(true, OptionType.CREATE_UPDATE, "--hash-dependencies") {
+ new Option(true, OptionType.CREATE_UPDATE, "--hash-modules") {
void process(Main jartool, String opt, String arg) throws BadArgs {
try {
- jartool.dependenciesToHash = Pattern.compile(arg);
+ jartool.modulesToHash = Pattern.compile(arg);
} catch (PatternSyntaxException e) {
throw new BadArgs("err.badpattern", arg).showUsage(true);
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Fri May 06 06:23:30 2016 -0700
@@ -26,21 +26,25 @@
package sun.tools.jar;
import java.io.*;
+import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Version;
import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
-import java.lang.reflect.Method;
+import java.lang.module.ResolutionException;
+import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Consumer;
-import java.util.regex.Matcher;
+import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.*;
@@ -49,9 +53,12 @@
import java.util.jar.Manifest;
import java.text.MessageFormat;
-import jdk.internal.module.Hasher;
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.util.jar.JarIndex;
+
import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
@@ -117,7 +124,7 @@
/* Modular jar related options */
boolean printModuleDescriptor;
Version moduleVersion;
- Pattern dependenciesToHash;
+ Pattern modulesToHash;
ModuleFinder moduleFinder = ModuleFinder.empty();
private static final String MODULE_INFO = "module-info.class";
@@ -241,7 +248,7 @@
if (isModularJar()) {
moduleInfoBytes = addExtendedModuleAttributes(
readModuleInfo(moduleInfo));
- } else if (moduleVersion != null || dependenciesToHash != null) {
+ } else if (moduleVersion != null || modulesToHash != null) {
error(getMsg("error.module.options.without.info"));
return false;
}
@@ -801,7 +808,7 @@
}
} else if (isModuleInfoEntry
&& ((newModuleInfoBytes != null) || (ename != null)
- || moduleVersion != null || dependenciesToHash != null)) {
+ || moduleVersion != null || modulesToHash != null)) {
if (newModuleInfoBytes == null) {
// Update existing module-info.class
newModuleInfoBytes = readModuleInfo(zis);
@@ -861,7 +868,7 @@
if (!updateModuleInfo(newModuleInfoBytes, zos)) {
updateOk = false;
}
- } else if (moduleVersion != null || dependenciesToHash != null) {
+ } else if (moduleVersion != null || modulesToHash != null) {
error(getMsg("error.module.options.without.info"));
updateOk = false;
}
@@ -1642,70 +1649,60 @@
return false;
}
- @SuppressWarnings("unchecked")
+ static <T> String toString(Set<T> set) {
+ if (set.isEmpty()) { return ""; }
+ return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
+ .collect(joining(" "));
+ }
+
+ private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
+
private void printModuleDescriptor(InputStream entryInputStream)
throws IOException
{
ModuleDescriptor md = ModuleDescriptor.read(entryInputStream);
StringBuilder sb = new StringBuilder();
- sb.append("\nName:\n " + md.toNameAndVersion());
-
- Set<Requires> requires = md.requires();
- if (!requires.isEmpty()) {
- sb.append("\nRequires:");
- requires.forEach(r ->
- sb.append("\n ").append(r.name())
- .append(toString(r.modifiers(), " [ ", " ]")));
- }
+ sb.append("\n").append(md.toNameAndVersion());
- Set<String> s = md.uses();
- if (!s.isEmpty()) {
- sb.append("\nUses: ");
- s.forEach(sv -> sb.append("\n ").append(sv));
- }
+ md.requires().stream()
+ .sorted(Comparator.comparing(Requires::name))
+ .forEach(r -> {
+ sb.append("\n requires ");
+ if (!r.modifiers().isEmpty())
+ sb.append(toString(r.modifiers())).append(" ");
+ sb.append(r.name());
+ });
- Set<Exports> exports = md.exports();
- if (!exports.isEmpty()) {
- sb.append("\nExports:");
- exports.forEach(sv -> sb.append("\n ").append(sv));
- }
+ md.uses().stream().sorted()
+ .forEach(p -> sb.append("\n uses ").append(p));
+
+ md.exports().stream()
+ .sorted(Comparator.comparing(Exports::source))
+ .forEach(p -> sb.append("\n exports ").append(p));
+
+ md.conceals().stream().sorted()
+ .forEach(p -> sb.append("\n conceals ").append(p));
- Map<String,Provides> provides = md.provides();
- if (!provides.isEmpty()) {
- sb.append("\nProvides: ");
- provides.values().forEach(p ->
- sb.append("\n ").append(p.service())
- .append(" with ")
- .append(toString(p.providers(), "", "")));
- }
+ md.provides().values().stream()
+ .sorted(Comparator.comparing(Provides::service))
+ .forEach(p -> sb.append("\n provides ").append(p.service())
+ .append(" with ")
+ .append(toString(p.providers())));
- Optional<String> mc = md.mainClass();
- if (mc.isPresent())
- sb.append("\nMain class:\n " + mc.get());
+ md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
+
+ md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v));
- s = md.conceals();
- if (!s.isEmpty()) {
- sb.append("\nConceals:");
- s.forEach(p -> sb.append("\n ").append(p));
- }
+ md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v));
- try {
- Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
- m.setAccessible(true);
- Optional<Hasher.DependencyHashes> optHashes =
- (Optional<Hasher.DependencyHashes>) m.invoke(md);
+ md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v));
- if (optHashes.isPresent()) {
- Hasher.DependencyHashes hashes = optHashes.get();
- sb.append("\nHashes:");
- sb.append("\n Algorithm: " + hashes.algorithm());
- hashes.names().stream().forEach(mod ->
- sb.append("\n ").append(mod)
- .append(": ").append(hashes.hashFor(mod)));
- }
- } catch (ReflectiveOperationException x) {
- throw new InternalError(x);
- }
+ JLMA.hashes(md).ifPresent(hashes ->
+ hashes.names().stream().sorted().forEach(
+ mod -> sb.append("\n hashes ").append(mod).append(" ")
+ .append(hashes.algorithm()).append(" ")
+ .append(hashes.hashFor(mod))));
+
output(sb.toString());
}
@@ -1751,7 +1748,6 @@
md = ModuleDescriptor.read(in);
}
String name = md.name();
- Set<ModuleDescriptor.Requires> dependences = md.requires();
Set<String> exported = md.exports()
.stream()
.map(ModuleDescriptor.Exports::source)
@@ -1778,9 +1774,17 @@
if (moduleVersion != null)
extender.version(moduleVersion);
- // --hash-dependencies
- if (dependenciesToHash != null)
- extender.hashes(hashDependences(name, dependences));
+ // --hash-modules
+ if (modulesToHash != null) {
+ Hasher hasher = new Hasher(md, fname);
+ ModuleHashes moduleHashes = hasher.computeHashes(name);
+ if (moduleHashes != null) {
+ extender.hashes(moduleHashes);
+ } else {
+ // should it issue warning or silent?
+ System.out.println("warning: no module is recorded in hash in " + name);
+ }
+ }
extender.write(baos);
return baos.toByteArray();
@@ -1788,36 +1792,156 @@
}
/**
- * Examines the module dependences of the given module and computes the
- * hash of any module that matches the pattern {@code dependenciesToHash}.
+ * Compute and record hashes
*/
- private Hasher.DependencyHashes
- hashDependences(String name,
- Set<ModuleDescriptor.Requires> moduleDependences)
- throws IOException
- {
- Map<String, Path> map = new HashMap<>();
- Matcher matcher = dependenciesToHash.matcher("");
- for (ModuleDescriptor.Requires md: moduleDependences) {
- String dn = md.name();
- if (matcher.reset(dn).find()) {
- Optional<ModuleReference> omref = moduleFinder.find(dn);
- if (!omref.isPresent()) {
- throw new IOException(formatMsg2("error.hash.dep", name , dn));
- }
- map.put(dn, modRefToPath(omref.get()));
+ private class Hasher {
+ final ModuleFinder finder;
+ final Map<String, Path> moduleNameToPath;
+ final Set<String> modules;
+ final Configuration configuration;
+ Hasher(ModuleDescriptor descriptor, String fname) throws IOException {
+ // Create a module finder that finds the modular JAR
+ // being created/updated
+ URI uri = Paths.get(fname).toUri();
+ ModuleReference mref = new ModuleReference(descriptor, uri,
+ new Supplier<>() {
+ @Override
+ public ModuleReader get() {
+ throw new UnsupportedOperationException("should not reach here");
+ }
+ });
+
+ // Compose a module finder with the module path and
+ // the modular JAR being created or updated
+ this.finder = ModuleFinder.compose(moduleFinder,
+ new ModuleFinder() {
+ @Override
+ public Optional<ModuleReference> find(String name) {
+ if (descriptor.name().equals(name))
+ return Optional.of(mref);
+ else
+ return Optional.empty();
+ }
+
+ @Override
+ public Set<ModuleReference> findAll() {
+ return Collections.singleton(mref);
+ }
+ });
+
+ // Determine the modules that matches the modulesToHash pattern
+ this.modules = moduleFinder.findAll().stream()
+ .map(moduleReference -> moduleReference.descriptor().name())
+ .filter(mn -> modulesToHash.matcher(mn).find())
+ .collect(Collectors.toSet());
+
+ // a map from a module name to Path of the modular JAR
+ this.moduleNameToPath = moduleFinder.findAll().stream()
+ .map(ModuleReference::descriptor)
+ .map(ModuleDescriptor::name)
+ .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
+
+ Configuration config = null;
+ try {
+ config = Configuration.empty()
+ .resolveRequires(ModuleFinder.ofSystem(), finder, modules);
+ } catch (ResolutionException e) {
+ // should it throw an error? or emit a warning
+ System.out.println("warning: " + e.getMessage());
}
+ this.configuration = config;
}
- if (map.size() == 0) {
- return null;
- } else {
- return Hasher.generate(map, "SHA-256");
+ /**
+ * Compute hashes of the modules that depend upon the specified
+ * module directly or indirectly.
+ */
+ ModuleHashes computeHashes(String name) {
+ // the transposed graph includes all modules in the resolved graph
+ Map<String, Set<String>> graph = transpose();
+
+ // find the modules that transitively depend upon the specified name
+ Deque<String> deque = new ArrayDeque<>();
+ deque.add(name);
+ Set<String> mods = visitNodes(graph, deque);
+
+ // filter modules matching the pattern specified --hash-modules
+ // as well as itself as the jmod file is being generated
+ Map<String, Path> modulesForHash = mods.stream()
+ .filter(mn -> !mn.equals(name) && modules.contains(mn))
+ .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
+
+ if (modulesForHash.isEmpty())
+ return null;
+
+ return ModuleHashes.generate(modulesForHash, "SHA-256");
+ }
+
+ /**
+ * Returns all nodes traversed from the given roots.
+ */
+ private Set<String> visitNodes(Map<String, Set<String>> graph,
+ Deque<String> roots) {
+ Set<String> visited = new HashSet<>();
+ while (!roots.isEmpty()) {
+ String mn = roots.pop();
+ if (!visited.contains(mn)) {
+ visited.add(mn);
+
+ // the given roots may not be part of the graph
+ if (graph.containsKey(mn)) {
+ for (String dm : graph.get(mn)) {
+ if (!visited.contains(dm))
+ roots.push(dm);
+ }
+ }
+ }
+ }
+ return visited;
+ }
+
+ /**
+ * Returns a transposed graph from the resolved module graph.
+ */
+ private Map<String, Set<String>> transpose() {
+ Map<String, Set<String>> transposedGraph = new HashMap<>();
+ Deque<String> deque = new ArrayDeque<>(modules);
+
+ Set<String> visited = new HashSet<>();
+ while (!deque.isEmpty()) {
+ String mn = deque.pop();
+ if (!visited.contains(mn)) {
+ visited.add(mn);
+
+ // add an empty set
+ transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
+
+ ResolvedModule resolvedModule = configuration.findModule(mn).get();
+ for (ResolvedModule dm : resolvedModule.reads()) {
+ String name = dm.name();
+ if (!visited.contains(name)) {
+ deque.push(name);
+ }
+ // reverse edge
+ transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
+ .add(mn);
+ }
+ }
+ }
+ return transposedGraph;
+ }
+
+ private Path moduleToPath(String name) {
+ ModuleReference mref = moduleFinder.find(name).orElseThrow(
+ () -> new InternalError(formatMsg2("error.hash.dep",name , name)));
+
+ URI uri = mref.location().get();
+ Path path = Paths.get(uri);
+ String fn = path.getFileName().toString();
+ if (!fn.endsWith(".jar")) {
+ throw new UnsupportedOperationException(path + " is not a modular JAR");
+ }
+ return path;
}
}
-
- private static Path modRefToPath(ModuleReference mref) {
- URI location = mref.location().get();
- return Paths.get(location);
- }
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Fri May 06 06:23:30 2016 -0700
@@ -57,7 +57,7 @@
error.hash.dep=\
Hashing module {0} dependences, unable to find module {1} on module path
error.module.options.without.info=\
- One of --module-version or --hash-dependencies without module-info.class
+ One of --module-version or --hash-modules without module-info.class
error.unexpected.module-info=\
Unexpected module descriptor {0}
error.module.descriptor.not.found=\
@@ -178,11 +178,11 @@
main.help.opt.create.update.module-version=\
\ --module-version=VERSION The module version, when creating a modular\n\
\ jar, or updating a non-modular jar
-main.help.opt.create.update.hash-dependencies=\
-\ --hash-dependencies=PATTERN Compute and record the hashes of module\n\
-\ dependencies matched by the given pattern, when\n\
-\ creating a modular jar, or updating a non-modular\n\
-\ jar
+main.help.opt.create.update.hash-modules=\
+\ --hash-modules=PATTERN Compute and record the hashes of modules \n\
+\ matched by the given pattern and that depend upon\n\
+\ directly or indirectly on a modular jar being\n\
+\ created or a non-modular jar being updated
main.help.opt.create.update.modulepath=\
\ --modulepath Location of module dependence for generating
\ the hash
@@ -201,7 +201,7 @@
\ located in the root of the given directories, or the root of the jar archive\n\
\ itself. The following operations are only valid when creating a modular jar,\n\
\ or updating an existing non-modular jar: '--module-version',\n\
-\ '--hash-dependencies', and '--modulepath'.\n\
+\ '--hash-modules', and '--modulepath'.\n\
\n\
\ Mandatory or optional arguments to long options are also mandatory or optional\n\
\ for any corresponding short options.
\ No newline at end of file
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java Fri May 06 06:23:30 2016 -0700
@@ -128,7 +128,9 @@
if (lib.equals("dt_shmem")) {
try {
Class<?> c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
- ts = (TransportService)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object tmp = c.newInstance();
+ ts = (TransportService)tmp;
} catch (Exception x) { }
}
}
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java Fri May 06 06:23:30 2016 -0700
@@ -53,17 +53,19 @@
super();
try {
- Class<?> c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
- transportService = (TransportService)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o =
+ Class.forName("com.sun.tools.jdi.SharedMemoryTransportService").newInstance();
+ transportService = (TransportService)o;
transport = new Transport() {
public String name() {
return "dt_shmem";
}
};
- } catch (ClassNotFoundException x) {
- } catch (UnsatisfiedLinkError x) {
- } catch (InstantiationException x) {
- } catch (IllegalAccessException x) {
+ } catch (ClassNotFoundException |
+ UnsatisfiedLinkError |
+ InstantiationException |
+ IllegalAccessException x) {
};
if (transportService == null) {
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java Fri May 06 06:23:30 2016 -0700
@@ -64,18 +64,20 @@
* transport or the socket transport
*/
try {
- Class<?> c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
- transportService = (TransportService)c.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o =
+ Class.forName("com.sun.tools.jdi.SharedMemoryTransportService").newInstance();
+ transportService = (TransportService)o;
transport = new Transport() {
public String name() {
return "dt_shmem";
}
};
usingSharedMemory = true;
- } catch (ClassNotFoundException x) {
- } catch (UnsatisfiedLinkError x) {
- } catch (InstantiationException x) {
- } catch (IllegalAccessException x) {
+ } catch (ClassNotFoundException |
+ UnsatisfiedLinkError |
+ InstantiationException |
+ IllegalAccessException x) {
};
if (transportService == null) {
transportService = new SocketTransportService();
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -95,27 +95,23 @@
private final Path root;
private final Path mdir;
- private final boolean genBom;
private final Set<String> modules = new HashSet<>();
/**
* Default image builder constructor.
*
- * @param genBom true, generates a bom file.
* @param root The image root directory.
* @throws IOException
*/
- public DefaultImageBuilder(boolean genBom, Path root) throws IOException {
+ public DefaultImageBuilder(Path root) throws IOException {
Objects.requireNonNull(root);
- this.genBom = genBom;
-
this.root = root;
this.mdir = root.resolve("lib");
Files.createDirectories(mdir);
}
- private void storeFiles(Set<String> modules, String bom, Properties release) throws IOException {
+ private void storeFiles(Set<String> modules, Properties release) throws IOException {
if (release != null) {
addModules(release, modules);
File r = new File(root.toFile(), "release");
@@ -123,11 +119,6 @@
release.store(fo, null);
}
}
- // Generate bom
- if (genBom) {
- File bomFile = new File(root.toFile(), "bom");
- createUtf8File(bomFile, bom);
- }
}
private void addModules(Properties release, Set<String> modules) throws IOException {
@@ -144,7 +135,7 @@
}
@Override
- public void storeFiles(Pool files, String bom, Properties release) {
+ public void storeFiles(Pool files, Properties release) {
try {
for (ModuleData f : files.getContent()) {
if (!f.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
@@ -161,7 +152,7 @@
modules.add(m.getName());
}
}
- storeFiles(modules, bom, release);
+ storeFiles(modules, release);
if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) {
// launchers in the bin directory need execute permission
@@ -190,8 +181,8 @@
}
@Override
- public void storeFiles(Pool files, String bom) {
- storeFiles(files, bom, new Properties());
+ public void storeFiles(Pool files) {
+ storeFiles(files, new Properties());
}
/**
@@ -213,28 +204,48 @@
mainClass = ModuleDescriptor.read(stream).mainClass();
if (mainClass.isPresent()) {
Path cmd = root.resolve("bin").resolve(module);
- if (!Files.exists(cmd)) {
- StringBuilder sb = new StringBuilder();
- sb.append("#!/bin/sh")
- .append("\n");
- sb.append("JLINK_VM_OPTIONS=")
- .append("\n");
- sb.append("DIR=`dirname $0`")
- .append("\n");
- sb.append("$DIR/java $JLINK_VM_OPTIONS -m ")
+ // generate shell script for Unix platforms
+ StringBuilder sb = new StringBuilder();
+ sb.append("#!/bin/sh")
+ .append("\n");
+ sb.append("JLINK_VM_OPTIONS=")
+ .append("\n");
+ sb.append("DIR=`dirname $0`")
+ .append("\n");
+ sb.append("$DIR/java $JLINK_VM_OPTIONS -m ")
+ .append(module).append('/')
+ .append(mainClass.get())
+ .append(" $@\n");
+
+ try (BufferedWriter writer = Files.newBufferedWriter(cmd,
+ StandardCharsets.ISO_8859_1,
+ StandardOpenOption.CREATE_NEW)) {
+ writer.write(sb.toString());
+ }
+ if (Files.getFileStore(root.resolve("bin"))
+ .supportsFileAttributeView(PosixFileAttributeView.class)) {
+ setExecutable(cmd);
+ }
+ // generate .bat file for Windows
+ if (isWindows()) {
+ Path bat = root.resolve("bin").resolve(module + ".bat");
+ sb = new StringBuilder();
+ sb.append("@echo off")
+ .append("\r\n");
+ sb.append("set JLINK_VM_OPTIONS=")
+ .append("\r\n");
+ sb.append("set DIR=%~dp0")
+ .append("\r\n");
+ sb.append("\"%DIR%\\java\" %JLINK_VM_OPTIONS% -m ")
.append(module).append('/')
.append(mainClass.get())
- .append(" $@\n");
+ .append(" %*\r\n");
- try (BufferedWriter writer = Files.newBufferedWriter(cmd,
+ try (BufferedWriter writer = Files.newBufferedWriter(bat,
StandardCharsets.ISO_8859_1,
StandardOpenOption.CREATE_NEW)) {
writer.write(sb.toString());
}
- if (Files.getFileStore(root.resolve("bin"))
- .supportsFileAttributeView(PosixFileAttributeView.class)) {
- setExecutable(cmd);
- }
}
}
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -42,22 +42,20 @@
* Store the external files.
*
* @param content Pool of module content.
- * @param bom The options used to build the image file.
* @param release the release properties
* @throws PluginException
*/
- public default void storeFiles(Pool content, String bom, Properties release) {
- storeFiles(content, bom);
+ public default void storeFiles(Pool content, Properties release) {
+ storeFiles(content);
}
/**
* Store the external files.
*
* @param content Pool of module content.
- * @param bom The options used to build the image file.
* @throws PluginException
*/
- public default void storeFiles(Pool content, String bom) {
+ public default void storeFiles(Pool content) {
throw new UnsupportedOperationException("storeFiles");
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java Fri May 06 06:23:30 2016 -0700
@@ -88,7 +88,7 @@
ByteOrder byteOrder)
throws IOException {
return ImageFileCreator.create(archives, byteOrder,
- new ImagePluginStack(null));
+ new ImagePluginStack());
}
public static ExecutableImage create(Set<Archive> archives,
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java Fri May 06 06:23:30 2016 -0700
@@ -68,20 +68,13 @@
private ImagePluginConfiguration() {
}
- public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration plugins)
- throws Exception {
- return parseConfiguration(plugins, null);
- }
-
/*
* Create a stack of plugins from a a configuration.
- *
*/
- public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration pluginsConfiguration,
- String bom)
+ public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration pluginsConfiguration)
throws Exception {
if (pluginsConfiguration == null) {
- return new ImagePluginStack(bom);
+ return new ImagePluginStack();
}
Map<Plugin.CATEGORY, List<Plugin>> plugins = new LinkedHashMap<>();
for (Plugin.CATEGORY cat : CATEGORIES_ORDER) {
@@ -150,7 +143,7 @@
}
@Override
- public void storeFiles(Pool files, String bom) {
+ public void storeFiles(Pool files) {
throw new PluginException("No directory setup to store files");
}
};
@@ -158,6 +151,6 @@
PluginContext ctxt = pluginsConfiguration.getPluginContext();
return new ImagePluginStack(builder, transformerPlugins,
- lastSorter, postProcessingPlugins, ctxt, bom);
+ lastSorter, postProcessingPlugins, ctxt);
}
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Fri May 06 06:23:30 2016 -0700
@@ -167,28 +167,25 @@
private final ImageBuilder imageBuilder;
private final Properties release;
- private final String bom;
+
+ public ImagePluginStack() {
+ this(null, Collections.emptyList(), null,
+ Collections.emptyList(), null);
+ }
- public ImagePluginStack(String bom) {
- this(null, Collections.emptyList(), null,
- Collections.emptyList(), null, bom);
+ public ImagePluginStack(ImageBuilder imageBuilder,
+ List<TransformerPlugin> contentPlugins,
+ Plugin lastSorter,
+ List<PostProcessorPlugin> postprocessingPlugins) {
+ this(imageBuilder, contentPlugins, lastSorter,
+ postprocessingPlugins, null);
}
public ImagePluginStack(ImageBuilder imageBuilder,
List<TransformerPlugin> contentPlugins,
Plugin lastSorter,
List<PostProcessorPlugin> postprocessingPlugins,
- String bom) {
- this(imageBuilder, contentPlugins, lastSorter,
- postprocessingPlugins, null, bom);
- }
-
- public ImagePluginStack(ImageBuilder imageBuilder,
- List<TransformerPlugin> contentPlugins,
- Plugin lastSorter,
- List<PostProcessorPlugin> postprocessingPlugins,
- PluginContext ctxt,
- String bom) {
+ PluginContext ctxt) {
Objects.requireNonNull(contentPlugins);
this.lastSorter = lastSorter;
for (TransformerPlugin p : contentPlugins) {
@@ -204,7 +201,6 @@
}
this.imageBuilder = imageBuilder;
this.release = ctxt != null? ctxt.getReleaseProperties() : new Properties();
- this.bom = bom;
}
public void operate(ImageProvider provider) throws Exception {
@@ -479,7 +475,7 @@
} catch (Exception ignored) {
}
- imageBuilder.storeFiles(new LastPool(transformed), bom, release);
+ imageBuilder.storeFiles(new LastPool(transformed), release);
}
public ExecutableImage getExecutableImage() throws IOException {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Fri May 06 06:23:30 2016 -0700
@@ -70,6 +70,7 @@
* ## Should use jdk.joptsimple some day.
*/
public class JlinkTask {
+ private static final boolean DEBUG = Boolean.getBoolean("jlink.debug");
private static <T extends Throwable> void fail(Class<T> type,
String format,
@@ -142,9 +143,6 @@
}
task.options.packagedModulesPath = path;
}, true, "--keep-packaged-modules"),
- new Option<JlinkTask>(false, (task, opt, arg) -> {
- task.options.genbom = true;
- }, true, "--genbom"),
new Option<JlinkTask>(true, (task, opt, arg) -> {
task.options.saveoptsfile = arg;
}, "--saveopts"),
@@ -175,7 +173,6 @@
static class OptionsValues {
boolean help;
- boolean genbom;
String saveoptsfile;
boolean version;
boolean fullVersion;
@@ -219,18 +216,24 @@
}
return EXIT_OK;
- } catch (UncheckedIOException | PluginException | IOException | ResolutionException e) {
+ } catch (UncheckedIOException | PluginException | IllegalArgumentException |
+ IOException | ResolutionException e) {
log.println(taskHelper.getMessage("error.prefix") + " " + e.getMessage());
- log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
+ if (DEBUG) {
+ e.printStackTrace(log);
+ }
return EXIT_ERROR;
} catch (BadArgs e) {
taskHelper.reportError(e.key, e.args);
if (e.showUsage) {
log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
}
+ if (DEBUG) {
+ e.printStackTrace(log);
+ }
return EXIT_CMDERR;
} catch (Throwable x) {
- log.println(taskHelper.getMessage("main.msg.bug"));
+ log.println(taskHelper.getMessage("error.prefix") + " " + x.getMessage());
x.printStackTrace(log);
return EXIT_ABNORMAL;
} finally {
@@ -238,16 +241,6 @@
}
}
- private static Map<String, Path> modulesToPath(Configuration cf) {
- Map<String, Path> modPaths = new HashMap<>();
- for (ResolvedModule resolvedModule : cf.modules()) {
- ModuleReference mref = resolvedModule.reference();
- URI uri = mref.location().get();
- modPaths.put(mref.descriptor().name(), Paths.get(uri));
- }
- return modPaths;
- }
-
/*
* Jlink API entry point.
*/
@@ -275,8 +268,7 @@
null);
// Then create the Plugin Stack
- ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins,
- genBOMContent(config, plugins));
+ ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins);
//Ask the stack to proceed;
stack.operate(imageProvider);
@@ -297,7 +289,7 @@
}
private void postProcessOnly(Path existingImage) throws Exception {
- PluginsConfiguration config = taskHelper.getPluginsConfig(null, false);
+ PluginsConfiguration config = taskHelper.getPluginsConfig(null);
ExecutableImage img = DefaultImageBuilder.getExecutableImage(existingImage);
if (img == null) {
throw taskHelper.newBadArgs("err.existing.image.invalid");
@@ -327,8 +319,7 @@
// Then create the Plugin Stack
ImagePluginStack stack = ImagePluginConfiguration.
- parseConfiguration(taskHelper.getPluginsConfig(options.output, options.genbom),
- genBOMContent());
+ parseConfiguration(taskHelper.getPluginsConfig(options.output));
//Ask the stack to proceed
stack.operate(imageProvider);
@@ -358,6 +349,15 @@
return finder;
}
+
+ private static Path toPathLocation(ResolvedModule m) {
+ Optional<URI> ouri = m.reference().location();
+ if (!ouri.isPresent())
+ throw new InternalError(m + " does not have a location");
+ URI uri = ouri.get();
+ return Paths.get(uri);
+ }
+
private static ImageProvider createImageProvider(ModuleFinder finder,
Set<String> addMods,
Set<String> limitMods,
@@ -374,7 +374,8 @@
ModuleFinder.empty(),
addMods);
- Map<String, Path> mods = modulesToPath(cf);
+ Map<String, Path> mods = cf.modules().stream()
+ .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation));
return new ImageHelper(cf, mods, order, retainModulesPath);
}
@@ -399,21 +400,15 @@
map.put(mref.descriptor().name(), mref);
});
+ // add the other modules
+ otherMods.stream()
+ .map(finder::find)
+ .flatMap(Optional::stream)
+ .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref));
+
// set of modules that are observable
Set<ModuleReference> mrefs = new HashSet<>(map.values());
- // add the other modules
- for (String mod : otherMods) {
- Optional<ModuleReference> omref = finder.find(mod);
- if (omref.isPresent()) {
- ModuleReference mref = omref.get();
- map.putIfAbsent(mod, mref);
- mrefs.add(mref);
- } else {
- // no need to fail
- }
- }
-
return new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Fri May 06 06:23:30 2016 -0700
@@ -337,8 +337,8 @@
return null;
}
- private PluginsConfiguration getPluginsConfig(Path output,
- boolean genbom) throws IOException, BadArgs {
+ private PluginsConfiguration getPluginsConfig(Path output
+ ) throws IOException, BadArgs {
if (output != null) {
if (Files.exists(output)) {
throw new PluginException(PluginsResourceBundle.
@@ -367,7 +367,7 @@
// recreate or postprocessing don't require an output directory.
ImageBuilder builder = null;
if (output != null) {
- builder = new DefaultImageBuilder(genbom, output);
+ builder = new DefaultImageBuilder(output);
}
return new Jlink.PluginsConfiguration(pluginsList,
@@ -676,9 +676,9 @@
+ bundleHelper.getMessage(key, args));
}
- public PluginsConfiguration getPluginsConfig(Path output, boolean genbom)
+ public PluginsConfiguration getPluginsConfig(Path output)
throws IOException, BadArgs {
- return pluginOptions.getPluginsConfig(output, genbom);
+ return pluginOptions.getPluginsConfig(output);
}
public Path getExistingImage() {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -139,7 +139,7 @@
// build the image
Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration(
- plugins, new DefaultImageBuilder(true, outputDir), null);
+ plugins, new DefaultImageBuilder(outputDir), null);
Jlink jlink = new Jlink();
jlink.build(jlinkConfig, pluginConfig);
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java Fri May 06 06:23:30 2016 -0700
@@ -125,7 +125,7 @@
zip = new ZipPlugin(resFilter);
break;
default:
- throw new PluginException("Invalid level " + level);
+ throw new IllegalArgumentException("Invalid compression level " + level);
}
} else {
ss = new StringSharingPlugin(resFilter);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java Fri May 06 06:23:30 2016 -0700
@@ -208,7 +208,7 @@
break;
}
default: {
- throw new PluginException("Unknown option " + value);
+ throw new IllegalArgumentException("Unknown exclude VM option: " + value);
}
}
predicate = new ResourceFilter(Utils.listParser.apply(exclude), true);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java Fri May 06 06:23:30 2016 -0700
@@ -164,7 +164,7 @@
try {
return new Locale.LanguageRange(s);
} catch (IllegalArgumentException iae) {
- throw new PluginException(String.format(
+ throw new IllegalArgumentException(String.format(
PluginsResourceBundle.getMessage(NAME + ".invalidtag"), s));
}
})
@@ -177,24 +177,28 @@
Pool.Module module = resources.getModule(MODULENAME);
// jdk.localedata module validation
- Set<String> packages = module.getAllPackages();
- if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
- throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") +
- LOCALEDATA_PACKAGES.stream()
- .filter(pn -> !packages.contains(pn))
- .collect(Collectors.joining(",\n\t")));
- }
+ if (module != null) {
+ Set<String> packages = module.getAllPackages();
+ if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
+ throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") +
+ LOCALEDATA_PACKAGES.stream()
+ .filter(pn -> !packages.contains(pn))
+ .collect(Collectors.joining(",\n\t")));
+ }
- available = Stream.concat(module.getContent().stream()
- .map(md -> p.matcher(md.getPath()))
- .filter(m -> m.matches())
- .map(m -> m.group("tag").replaceAll("_", "-")),
- Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag)))
- .distinct()
- .sorted()
- .map(IncludeLocalesPlugin::tagToLocale)
- .collect(Collectors.toList());
-
+ available = Stream.concat(module.getContent().stream()
+ .map(md -> p.matcher(md.getPath()))
+ .filter(m -> m.matches())
+ .map(m -> m.group("tag").replaceAll("_", "-")),
+ Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag)))
+ .distinct()
+ .sorted()
+ .map(IncludeLocalesPlugin::tagToLocale)
+ .collect(Collectors.toList());
+ } else {
+ // jdk.localedata is not added.
+ throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".localedatanotfound"));
+ }
filtered = filterLocales(available);
if (filtered.isEmpty()) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java Fri May 06 06:23:30 2016 -0700
@@ -273,7 +273,7 @@
} else if (s.equals(FORNAME_REMOVAL)) {
optimizers.add(new ForNameFolding());
} else {
- throw new PluginException("Unknown optimization");
+ throw new IllegalArgumentException("Unknown optimization: " + s);
}
}
String f = config.get(LOG);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java Fri May 06 06:23:30 2016 -0700
@@ -39,6 +39,8 @@
import java.util.Set;
import java.util.stream.Collectors;
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.Checks;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.SystemModules;
@@ -50,6 +52,7 @@
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.Pool;
import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.Builder.*;
/**
* Jlink plugin to reconstitute module descriptors for installed modules.
@@ -63,6 +66,8 @@
* @see SystemModules
*/
public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
+ private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
+
// TODO: packager has the dependency on the plugin name
// Keep it as "--installed-modules" until packager removes such
// dependency (should not need to specify this plugin since it
@@ -118,7 +123,8 @@
Pool.ModuleData data = module.get("module-info.class");
if (data == null) {
// automatic module not supported yet
- throw new PluginException("module-info.class not found for " + module.getName() + " module");
+ throw new PluginException("module-info.class not found for " +
+ module.getName() + " module");
}
assert module.getName().equals(data.getModule());
try {
@@ -126,15 +132,20 @@
ModuleDescriptor md = ModuleDescriptor.read(bain);
validateNames(md);
- Builder.ModuleDescriptorBuilder mbuilder = builder.module(md, module.getAllPackages());
+ ModuleDescriptorBuilder mbuilder = builder.module(md, module.getAllPackages());
+ int packages = md.exports().size() + md.conceals().size();
if (md.conceals().isEmpty() &&
- (md.exports().size() + md.conceals().size()) != module.getAllPackages().size()) {
+ packages != module.getAllPackages().size()) {
// add ConcealedPackages attribute if not exist
bain.reset();
- ModuleInfoRewriter minfoWriter = new ModuleInfoRewriter(bain, mbuilder.conceals());
+ ModuleInfoRewriter minfoWriter =
+ new ModuleInfoRewriter(bain, mbuilder.conceals());
// replace with the overridden version
- data = new Pool.ModuleData(data.getModule(), data.getPath(), data.getType(),
- minfoWriter.stream(), minfoWriter.size());
+ data = new Pool.ModuleData(data.getModule(),
+ data.getPath(),
+ data.getType(),
+ minfoWriter.stream(),
+ minfoWriter.size());
}
out.add(data);
} catch (IOException e) {
@@ -151,8 +162,12 @@
if (builder.isOverriddenClass(data.getPath())) {
byte[] bytes = cwriter.toByteArray();
- Pool.ModuleData ndata = new Pool.ModuleData(data.getModule(), data.getPath(), data.getType(),
- new ByteArrayInputStream(bytes), bytes.length);
+ Pool.ModuleData ndata =
+ new Pool.ModuleData(data.getModule(),
+ data.getPath(),
+ data.getType(),
+ new ByteArrayInputStream(bytes),
+ bytes.length);
out.add(ndata);
} else {
out.add(data);
@@ -230,6 +245,7 @@
// static variables in SystemModules class
private static final String MODULE_NAMES = "MODULE_NAMES";
+ private static final String MODULES_TO_HASH = "MODULES_TO_HASH";
private static final String PACKAGE_COUNT = "PACKAGES_IN_BOOT_LAYER";
private static final int BUILDER_VAR = 0;
@@ -246,6 +262,9 @@
// list of all ModuleDescriptorBuilders, invoked in turn when building.
private final List<ModuleDescriptorBuilder> builders = new ArrayList<>();
+ // module name to hash
+ private final Map<String, String> modulesToHash = new HashMap<>();
+
// map Set<String> to a specialized builder to allow them to be
// deduplicated as they are requested
private final Map<Set<String>, StringSetBuilder> stringSets = new HashMap<>();
@@ -268,6 +287,11 @@
"[Ljava/lang/String;", null, null)
.visitEnd();
+ // public static String[] MODULES_TO_HASH = new String[] {....};
+ cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, MODULES_TO_HASH,
+ "[Ljava/lang/String;", null, null)
+ .visitEnd();
+
// public static int PACKAGES_IN_BOOT_LAYER;
cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, PACKAGE_COUNT,
"I", null, numPackages)
@@ -283,15 +307,35 @@
int index = 0;
for (ModuleDescriptorBuilder builder : builders) {
- mv.visitInsn(DUP); // arrayref
+ mv.visitInsn(DUP); // arrayref
pushInt(index++);
- mv.visitLdcInsn(builder.md.name()); // value
+ mv.visitLdcInsn(builder.md.name()); // value
mv.visitInsn(AASTORE);
}
mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULE_NAMES,
"[Ljava/lang/String;");
+ // create the MODULES_TO_HASH array
+ pushInt(numModules);
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+
+ index = 0;
+ for (ModuleDescriptorBuilder builder : builders) {
+ String mn = builder.md.name();
+ String recordedHash = modulesToHash.get(mn);
+ if (recordedHash != null) {
+ mv.visitInsn(DUP); // arrayref
+ pushInt(index);
+ mv.visitLdcInsn(recordedHash); // value
+ mv.visitInsn(AASTORE);
+ }
+ index++;
+ }
+
+ mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULES_TO_HASH,
+ "[Ljava/lang/String;");
+
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
@@ -315,15 +359,19 @@
}
}
- // provides
+ // provides (preserve iteration order)
for (ModuleDescriptor.Provides p : md.provides().values()) {
- stringSets.computeIfAbsent(p.providers(), s -> new StringSetBuilder(s))
+ stringSets.computeIfAbsent(p.providers(), s -> new StringSetBuilder(s, true))
.increment();
}
// uses
stringSets.computeIfAbsent(md.uses(), s -> new StringSetBuilder(s))
.increment();
+
+ // hashes
+ JLMA.hashes(md).ifPresent(mh -> modulesToHash.putAll(mh.hashes()));
+
return builder;
}
@@ -484,13 +532,17 @@
conceals(pn);
}
- if (md.version().isPresent()) {
- version(md.version().get());
- }
+ // version
+ md.version().ifPresent(this::version);
+
+ // main class
+ md.mainClass().ifPresent(this::mainClass);
- if (md.mainClass().isPresent()) {
- mainClass(md.mainClass().get());
- }
+ // hashes
+ JLMA.hashes(md).ifPresent(mh -> {
+ algorithm(mh.algorithm());
+ mh.names().forEach(mn -> moduleHash(mn, mh.hashFor(mn)));
+ });
putModuleDescriptor();
}
@@ -603,7 +655,7 @@
/*
* Invoke Builder.provides(String service, Set<String> providers)
*
- * Set<String> providers = new HashSet<>();
+ * Set<String> providers = new LinkedHashSet<>();
* providers.add(impl);
* :
* :
@@ -652,6 +704,22 @@
mv.visitInsn(POP);
}
+ void algorithm(String alg) {
+ mv.visitVarInsn(ALOAD, BUILDER_VAR);
+ mv.visitLdcInsn(alg);
+ mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+ "algorithm", STRING_SIG, false);
+ mv.visitInsn(POP);
+ }
+
+ void moduleHash(String name, String hashString) {
+ mv.visitVarInsn(ALOAD, BUILDER_VAR);
+ mv.visitLdcInsn(name);
+ mv.visitLdcInsn(hashString);
+ mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+ "moduleHash", STRING_STRING_SIG, false);
+ mv.visitInsn(POP);
+ }
}
/*
@@ -663,10 +731,17 @@
*/
class StringSetBuilder {
final Set<String> names;
+ final boolean linked;
int refCount;
int localVarIndex;
+
+ StringSetBuilder(Set<String> names, boolean linked) {
+ this.names = names;
+ this.linked = linked;
+ }
+
StringSetBuilder(Set<String> names) {
- this.names = names;
+ this(names, false);
}
void increment() {
@@ -704,11 +779,11 @@
"singleton", "(Ljava/lang/Object;)Ljava/util/Set;", false);
mv.visitVarInsn(ASTORE, index);
} else {
- mv.visitTypeInsn(NEW, "java/util/HashSet");
+ String cn = linked ? "java/util/LinkedHashSet" : "java/util/HashSet";
+ mv.visitTypeInsn(NEW, cn);
mv.visitInsn(DUP);
pushInt(initialCapacity(names.size()));
- mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet",
- "<init>", "(I)V", false);
+ mv.visitMethodInsn(INVOKESPECIAL, cn, "<init>", "(I)V", false);
mv.visitVarInsn(ASTORE, index);
for (String t : names) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java Fri May 06 06:23:30 2016 -0700
@@ -201,6 +201,8 @@
* This method is called prior to invoke the plugin.
*
* @param config The plugin configuration.
+ * @throws IllegalArgumentException if a mandatory argument is missing or
+ * if an argument has invalid value.
*/
public default void configure(Map<String, String> config) {
}
@@ -211,6 +213,9 @@
*
* @param config The plugin configuration.
* @param ctx The plugin context
+ * @throws IllegalArgumentException if a mandatory argument is missing or
+ * if an argument has invalid value.
+ *
*/
public default void configure(Map<String, String> config, PluginContext ctx) {
configure(config);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Fri May 06 06:23:30 2016 -0700
@@ -33,9 +33,6 @@
main.opt.endian=\
\ --endian <little|big> Byte order of generated jimage (default:native)
-main.opt.genbom=\
-\ --genbom Generate a bom file containing jlink info
-
main.opt.saveopts=\
\ --saveopts <filename> Save jlink options in the given file
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Fri May 06 06:23:30 2016 -0700
@@ -89,6 +89,9 @@
include-locales.invalidtag=\
Invalid language tag: %s
+include-locales.localedatanotfound=\
+jdk.localedata module was not specified with --addmods option
+
main.status.ok=Functional.
main.status.not.ok= Not functional.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Fri May 06 06:23:30 2016 -0700
@@ -26,6 +26,7 @@
package jdk.tools.jmod;
import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -34,14 +35,17 @@
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UncheckedIOException;
-import java.lang.module.FindException;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Version;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import java.lang.module.ResolutionException;
+import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
@@ -51,13 +55,16 @@
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.MessageFormat;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Formatter;
+import java.util.Comparator;
+import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -68,6 +75,7 @@
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.jar.JarEntry;
@@ -89,16 +97,14 @@
import jdk.internal.joptsimple.OptionSet;
import jdk.internal.joptsimple.OptionSpec;
import jdk.internal.joptsimple.ValueConverter;
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.ConfigurableModuleFinder;
import jdk.internal.module.ConfigurableModuleFinder.Phase;
-import jdk.internal.module.Hasher;
-import jdk.internal.module.Hasher.DependencyHashes;
+import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfoExtender;
-import static java.util.function.Function.identity;
import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
/**
* Implementation for the jmod tool.
@@ -127,21 +133,6 @@
}
}
- static <T extends Throwable> void fail(Class<T> type,
- String format,
- Object... args) throws T {
- String msg = new Formatter().format(format, args).toString();
- try {
- T t = type.getConstructor(String.class).newInstance(msg);
- throw t;
- } catch (InstantiationException |
- InvocationTargetException |
- NoSuchMethodException |
- IllegalAccessException e) {
- throw new InternalError("Unable to create an instance of " + type, e);
- }
- }
-
private static final String PROGNAME = "jmod";
private static final String MODULE_INFO = "module-info.class";
@@ -161,7 +152,8 @@
enum Mode {
CREATE,
LIST,
- DESCRIBE
+ DESCRIBE,
+ HASH
};
static class Options {
@@ -179,7 +171,8 @@
String osName;
String osArch;
String osVersion;
- Pattern dependenciesToHash;
+ Pattern modulesToHash;
+ boolean dryrun;
List<PathMatcher> excludes;
}
@@ -211,6 +204,9 @@
case DESCRIBE:
ok = describe();
break;
+ case HASH:
+ ok = hashModules();
+ break;
default:
throw new AssertionError("Unknown mode: " + options.mode.name());
}
@@ -248,26 +244,8 @@
}
}
- private Map<String, Path> modulesToPath(Set<ModuleDescriptor> modules) {
- ModuleFinder finder = options.moduleFinder;
-
- Map<String,Path> modPaths = new HashMap<>();
- for (ModuleDescriptor m : modules) {
- String name = m.name();
-
- Optional<ModuleReference> omref = finder.find(name);
- if (!omref.isPresent()) {
- // this should not happen, module path bug?
- fail(InternalError.class,
- "Selected module %s not on module path",
- name);
- }
-
- URI uri = omref.get().location().get();
- modPaths.put(name, Paths.get(uri));
-
- }
- return modPaths;
+ private boolean hashModules() {
+ return new Hasher(options.moduleFinder).run();
}
private boolean describe() throws IOException {
@@ -297,6 +275,8 @@
.collect(joining(" "));
}
+ private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
+
private boolean printModuleDescriptor(InputStream in)
throws IOException
{
@@ -311,74 +291,45 @@
StringBuilder sb = new StringBuilder();
sb.append("\n").append(md.toNameAndVersion());
- List<Requires> requires = md.requires().stream().sorted().collect(toList());
- if (!requires.isEmpty()) {
- requires.forEach(r -> {
- sb.append("\n requires ");
- if (!r.modifiers().isEmpty())
- sb.append(toString(r.modifiers())).append(" ");
- sb.append(r.name());
- });
- }
-
- List<String> l = md.uses().stream().sorted().collect(toList());
- if (!l.isEmpty()) {
- l.forEach(sv -> sb.append("\n uses ").append(sv));
- }
+ md.requires().stream()
+ .sorted(Comparator.comparing(Requires::name))
+ .forEach(r -> {
+ sb.append("\n requires ");
+ if (!r.modifiers().isEmpty())
+ sb.append(toString(r.modifiers())).append(" ");
+ sb.append(r.name());
+ });
- List<ModuleDescriptor.Exports> exports = sortExports(md.exports());
- if (!exports.isEmpty()) {
- exports.forEach(ex -> sb.append("\n exports ").append(ex));
- }
+ md.uses().stream().sorted()
+ .forEach(s -> sb.append("\n uses ").append(s));
- l = md.conceals().stream().sorted().collect(toList());
- if (!l.isEmpty()) {
- l.forEach(p -> sb.append("\n conceals ").append(p));
- }
+ md.exports().stream()
+ .sorted(Comparator.comparing(Exports::source))
+ .forEach(p -> sb.append("\n exports ").append(p));
- Map<String, ModuleDescriptor.Provides> provides = md.provides();
- if (!provides.isEmpty()) {
- provides.values().forEach(p ->
- sb.append("\n provides ").append(p.service())
- .append(" with ")
- .append(toString(p.providers())));
- }
+ md.conceals().stream().sorted()
+ .forEach(p -> sb.append("\n conceals ").append(p));
- Optional<String> mc = md.mainClass();
- if (mc.isPresent())
- sb.append("\n main-class " + mc.get());
-
-
+ md.provides().values().stream()
+ .sorted(Comparator.comparing(Provides::service))
+ .forEach(p -> sb.append("\n provides ").append(p.service())
+ .append(" with ")
+ .append(toString(p.providers())));
- Optional<String> osname = md.osName();
- if (osname.isPresent())
- sb.append("\n operating-system-name " + osname.get());
+ md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
- Optional<String> osarch = md.osArch();
- if (osarch.isPresent())
- sb.append("\n operating-system-architecture " + osarch.get());
-
- Optional<String> osversion = md.osVersion();
- if (osversion.isPresent())
- sb.append("\n operating-system-version " + osversion.get());
+ md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v));
- try {
- Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
- m.setAccessible(true);
- @SuppressWarnings("unchecked")
- Optional<Hasher.DependencyHashes> optHashes =
- (Optional<Hasher.DependencyHashes>) m.invoke(md);
+ md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v));
+
+ md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v));
- if (optHashes.isPresent()) {
- Hasher.DependencyHashes hashes = optHashes.get();
- hashes.names().stream().forEach(mod ->
- sb.append("\n hashes ").append(mod).append(" ")
- .append(hashes.algorithm()).append(" ")
- .append(hashes.hashFor(mod)));
- }
- } catch (ReflectiveOperationException x) {
- throw new InternalError(x);
- }
+ JLMA.hashes(md).ifPresent(
+ hashes -> hashes.names().stream().sorted().forEach(
+ mod -> sb.append("\n hashes ").append(mod).append(" ")
+ .append(hashes.algorithm()).append(" ")
+ .append(hashes.hashFor(mod))));
+
out.println(sb.toString());
return true;
}
@@ -387,21 +338,6 @@
return false;
}
- static List<ModuleDescriptor.Exports> sortExports(Set<ModuleDescriptor.Exports> exports) {
- Map<String,ModuleDescriptor.Exports> map =
- exports.stream()
- .collect(toMap(ModuleDescriptor.Exports::source,
- identity()));
- List<String> sources = exports.stream()
- .map(ModuleDescriptor.Exports::source)
- .sorted()
- .collect(toList());
-
- List<ModuleDescriptor.Exports> l = new ArrayList<>();
- sources.forEach(e -> l.add(map.get(e)));
- return l;
- }
-
private boolean create() throws IOException {
JmodFileWriter jmod = new JmodFileWriter();
@@ -410,8 +346,9 @@
Path target = options.jmodFile;
Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
try {
- try (OutputStream out = Files.newOutputStream(tempTarget)) {
- jmod.write(out);
+ try (OutputStream out = Files.newOutputStream(tempTarget);
+ BufferedOutputStream bos = new BufferedOutputStream(out)) {
+ jmod.write(bos);
}
Files.move(tempTarget, target);
} catch (Exception e) {
@@ -428,7 +365,6 @@
}
private class JmodFileWriter {
- final ModuleFinder moduleFinder = options.moduleFinder;
final List<Path> cmds = options.cmds;
final List<Path> libs = options.libs;
final List<Path> configs = options.configs;
@@ -438,8 +374,8 @@
final String osName = options.osName;
final String osArch = options.osArch;
final String osVersion = options.osVersion;
- final Pattern dependenciesToHash = options.dependenciesToHash;
final List<PathMatcher> excludes = options.excludes;
+ final Hasher hasher = hasher();
JmodFileWriter() { }
@@ -545,11 +481,13 @@
if (moduleVersion != null)
extender.version(moduleVersion);
- // --hash-dependencies
- if (dependenciesToHash != null) {
- String name = descriptor.name();
- Set<Requires> dependences = descriptor.requires();
- extender.hashes(hashDependences(name, dependences));
+ if (hasher != null) {
+ ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name());
+ if (moduleHashes != null) {
+ extender.hashes(moduleHashes);
+ } else {
+ warning("warn.no.module.hashes", descriptor.name());
+ }
}
// write the (possibly extended or modified) module-info.class
@@ -561,38 +499,56 @@
}
}
- /**
- * Examines the module dependences of the given module
- * and computes the hash of any module that matches the
- * pattern {@code dependenciesToHash}.
+ /*
+ * Hasher resolves a module graph using the --hash-modules PATTERN
+ * as the roots.
+ *
+ * The jmod file is being created and does not exist in the
+ * given modulepath.
*/
- DependencyHashes hashDependences(String name, Set<Requires> moduleDependences)
- throws IOException
- {
- Set<ModuleDescriptor> descriptors = new HashSet<>();
- for (Requires md: moduleDependences) {
- String dn = md.name();
- if (dependenciesToHash.matcher(dn).find()) {
- try {
- Optional<ModuleReference> omref = moduleFinder.find(dn);
- if (!omref.isPresent()) {
- throw new RuntimeException("Hashing module " + name
- + " dependencies, unable to find module " + dn
- + " on module path");
+ private Hasher hasher() {
+ if (options.modulesToHash == null)
+ return null;
+
+ try {
+ Supplier<InputStream> miSupplier = newModuleInfoSupplier();
+ if (miSupplier == null) {
+ throw new IOException(MODULE_INFO + " not found");
+ }
+
+ ModuleDescriptor descriptor;
+ try (InputStream in = miSupplier.get()) {
+ descriptor = ModuleDescriptor.read(in);
+ }
+
+ URI uri = options.jmodFile.toUri();
+ ModuleReference mref = new ModuleReference(descriptor, uri, new Supplier<>() {
+ @Override
+ public ModuleReader get() {
+ throw new UnsupportedOperationException();
+ }
+ });
+
+ // compose a module finder with the module path and also
+ // a module finder that can find the jmod file being created
+ ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
+ new ModuleFinder() {
+ @Override
+ public Optional<ModuleReference> find(String name) {
+ if (descriptor.name().equals(name))
+ return Optional.of(mref);
+ else return Optional.empty();
}
- descriptors.add(omref.get().descriptor());
- } catch (FindException x) {
- throw new IOException("error reading module path", x);
- }
- }
- }
- Map<String, Path> map = modulesToPath(descriptors);
- if (map.size() == 0) {
- return null;
- } else {
- // use SHA-256 for now, easy to make this configurable if needed
- return Hasher.generate(map, "SHA-256");
+ @Override
+ public Set<ModuleReference> findAll() {
+ return Collections.singleton(mref);
+ }
+ });
+
+ return new Hasher(finder);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
}
}
@@ -765,6 +721,273 @@
}
}
+ /**
+ * Compute and record hashes
+ */
+ private class Hasher {
+ final ModuleFinder moduleFinder;
+ final Map<String, Path> moduleNameToPath;
+ final Set<String> modules;
+ final Configuration configuration;
+ final boolean dryrun = options.dryrun;
+ Hasher(ModuleFinder finder) {
+ this.moduleFinder = finder;
+ // Determine the modules that matches the pattern {@code modulesToHash}
+ this.modules = moduleFinder.findAll().stream()
+ .map(mref -> mref.descriptor().name())
+ .filter(mn -> options.modulesToHash.matcher(mn).find())
+ .collect(Collectors.toSet());
+
+ // a map from a module name to Path of the packaged module
+ this.moduleNameToPath = moduleFinder.findAll().stream()
+ .map(mref -> mref.descriptor().name())
+ .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
+
+ // get a resolved module graph
+ Configuration config = null;
+ try {
+ config = Configuration.empty()
+ .resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules);
+ } catch (ResolutionException e) {
+ warning("warn.module.resolution.fail", e.getMessage());
+ }
+ this.configuration = config;
+ }
+
+ /**
+ * This method is for jmod hash command.
+ *
+ * Identify the base modules in the module graph, i.e. no outgoing edge
+ * to any of the modules to be hashed.
+ *
+ * For each base module M, compute the hashes of all modules that depend
+ * upon M directly or indirectly. Then update M's module-info.class
+ * to record the hashes.
+ */
+ boolean run() {
+ if (configuration == null)
+ return false;
+
+ // transposed graph containing the the packaged modules and
+ // its transitive dependences matching --hash-modules
+ Map<String, Set<String>> graph = new HashMap<>();
+ for (String root : modules) {
+ Deque<String> deque = new ArrayDeque<>();
+ deque.add(root);
+ Set<String> visited = new HashSet<>();
+ while (!deque.isEmpty()) {
+ String mn = deque.pop();
+ if (!visited.contains(mn)) {
+ visited.add(mn);
+
+ if (modules.contains(mn))
+ graph.computeIfAbsent(mn, _k -> new HashSet<>());
+
+ ResolvedModule resolvedModule = configuration.findModule(mn).get();
+ for (ResolvedModule dm : resolvedModule.reads()) {
+ String name = dm.name();
+ if (!visited.contains(name)) {
+ deque.push(name);
+ }
+
+ // reverse edge
+ if (modules.contains(name) && modules.contains(mn)) {
+ graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn);
+ }
+ }
+ }
+ }
+ }
+
+ if (dryrun)
+ out.println("Dry run:");
+
+ // each node in a transposed graph is a matching packaged module
+ // in which the hash of the modules that depend upon it is recorded
+ graph.entrySet().stream()
+ .filter(e -> !e.getValue().isEmpty())
+ .forEach(e -> {
+ String mn = e.getKey();
+ Map<String, Path> modulesForHash = e.getValue().stream()
+ .collect(Collectors.toMap(Function.identity(),
+ moduleNameToPath::get));
+ ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256");
+ if (dryrun) {
+ out.format("%s%n", mn);
+ hashes.names().stream()
+ .sorted()
+ .forEach(name -> out.format(" hashes %s %s %s%n",
+ name, hashes.algorithm(), hashes.hashFor(name)));
+ } else {
+ try {
+ updateModuleInfo(mn, hashes);
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+ });
+ return true;
+ }
+
+ /**
+ * Compute hashes of the specified module.
+ *
+ * It records the hashing modules that depend upon the specified
+ * module directly or indirectly.
+ */
+ ModuleHashes computeHashes(String name) {
+ if (configuration == null)
+ return null;
+
+ // the transposed graph includes all modules in the resolved graph
+ Map<String, Set<String>> graph = transpose();
+
+ // find the modules that transitively depend upon the specified name
+ Deque<String> deque = new ArrayDeque<>();
+ deque.add(name);
+ Set<String> mods = visitNodes(graph, deque);
+
+ // filter modules matching the pattern specified --hash-modules
+ // as well as itself as the jmod file is being generated
+ Map<String, Path> modulesForHash = mods.stream()
+ .filter(mn -> !mn.equals(name) && modules.contains(mn))
+ .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
+
+ if (modulesForHash.isEmpty())
+ return null;
+
+ return ModuleHashes.generate(modulesForHash, "SHA-256");
+ }
+
+ /**
+ * Returns all nodes traversed from the given roots.
+ */
+ private Set<String> visitNodes(Map<String, Set<String>> graph,
+ Deque<String> roots) {
+ Set<String> visited = new HashSet<>();
+ while (!roots.isEmpty()) {
+ String mn = roots.pop();
+ if (!visited.contains(mn)) {
+ visited.add(mn);
+ // the given roots may not be part of the graph
+ if (graph.containsKey(mn)) {
+ for (String dm : graph.get(mn)) {
+ if (!visited.contains(dm)) {
+ roots.push(dm);
+ }
+ }
+ }
+ }
+ }
+ return visited;
+ }
+
+ /**
+ * Returns a transposed graph from the resolved module graph.
+ */
+ private Map<String, Set<String>> transpose() {
+ Map<String, Set<String>> transposedGraph = new HashMap<>();
+ Deque<String> deque = new ArrayDeque<>(modules);
+
+ Set<String> visited = new HashSet<>();
+ while (!deque.isEmpty()) {
+ String mn = deque.pop();
+ if (!visited.contains(mn)) {
+ visited.add(mn);
+
+ transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
+
+ ResolvedModule resolvedModule = configuration.findModule(mn).get();
+ for (ResolvedModule dm : resolvedModule.reads()) {
+ String name = dm.name();
+ if (!visited.contains(name)) {
+ deque.push(name);
+ }
+
+ // reverse edge
+ transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
+ .add(mn);
+ }
+ }
+ }
+ return transposedGraph;
+ }
+
+ /**
+ * Reads the given input stream of module-info.class and write
+ * the extended module-info.class with the given ModuleHashes
+ *
+ * @param in InputStream of module-info.class
+ * @param out OutputStream to write the extended module-info.class
+ * @param hashes ModuleHashes
+ */
+ private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes)
+ throws IOException
+ {
+ ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
+ extender.hashes(hashes);
+ extender.write(out);
+ }
+
+ private void updateModuleInfo(String name, ModuleHashes moduleHashes)
+ throws IOException
+ {
+ Path target = moduleNameToPath.get(name);
+ Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
+ ZipFile zip = new ZipFile(target.toFile());
+ try {
+ try (OutputStream out = Files.newOutputStream(tempTarget);
+ ZipOutputStream zos = new ZipOutputStream(out)) {
+ zip.stream().forEach(e -> {
+ try {
+ InputStream in = zip.getInputStream(e);
+ if (e.getName().equals(MODULE_INFO) ||
+ e.getName().equals(Section.CLASSES.jmodDir() + "/" + MODULE_INFO)) {
+ ZipEntry ze = new ZipEntry(e.getName());
+ ze.setTime(System.currentTimeMillis());
+ zos.putNextEntry(ze);
+ recordHashes(in, zos, moduleHashes);
+ zos.closeEntry();
+ } else {
+ zos.putNextEntry(e);
+ zos.write(in.readAllBytes());
+ zos.closeEntry();
+ }
+ } catch (IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ });
+ }
+ } catch (IOException|RuntimeException e) {
+ if (Files.exists(tempTarget)) {
+ try {
+ Files.delete(tempTarget);
+ } catch (IOException ioe) {
+ e.addSuppressed(ioe);
+ }
+ }
+ throw e;
+ } finally {
+ zip.close();
+ }
+ out.println(getMessage("module.hashes.recorded", name));
+ Files.move(tempTarget, target, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ private Path moduleToPath(String name) {
+ ModuleReference mref = moduleFinder.find(name).orElseThrow(
+ () -> new InternalError("Selected module " + name + " not on module path"));
+
+ URI uri = mref.location().get();
+ Path path = Paths.get(uri);
+ String fn = path.getFileName().toString();
+ if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+ throw new InternalError(path + " is not a modular JAR or jmod file");
+ }
+ return path;
+ }
+ }
+
enum Section {
NATIVE_LIBS("native"),
NATIVE_CMDS("bin"),
@@ -921,7 +1144,8 @@
builder.append("\n").append(" Main operation modes:\n ");
builder.append(getMessage("main.opt.mode.create")).append("\n ");
builder.append(getMessage("main.opt.mode.list")).append("\n ");
- builder.append(getMessage("main.opt.mode.describe")).append("\n\n");
+ builder.append(getMessage("main.opt.mode.describe")).append("\n ");
+ builder.append(getMessage("main.opt.mode.hash")).append("\n\n");
String cmdfile = null;
String[] lines = content.split("\n");
@@ -964,13 +1188,16 @@
.withValuesSeparatedBy(File.pathSeparatorChar)
.withValuesConvertedBy(DirPathConverter.INSTANCE);
+ OptionSpec<Void> dryrun
+ = parser.accepts("dry-run", getMessage("main.opt.dry-run"));
+
OptionSpec<PathMatcher> excludes
= parser.accepts("exclude", getMessage("main.opt.exclude"))
.withRequiredArg()
.withValuesConvertedBy(new GlobConverter());
- OptionSpec<Pattern> hashDependencies
- = parser.accepts("hash-dependencies", getMessage("main.opt.hash-dependencies"))
+ OptionSpec<Pattern> hashModules
+ = parser.accepts("hash-modules", getMessage("main.opt.hash-modules"))
.withRequiredArg()
.withValuesConvertedBy(new PatternConverter());
@@ -1049,6 +1276,8 @@
options.cmds = opts.valuesOf(cmds);
if (opts.has(config))
options.configs = opts.valuesOf(config);
+ if (opts.has(dryrun))
+ options.dryrun = true;
if (opts.has(excludes))
options.excludes = opts.valuesOf(excludes);
if (opts.has(libs))
@@ -1069,27 +1298,39 @@
options.osArch = opts.valueOf(osArch);
if (opts.has(osVersion))
options.osVersion = opts.valueOf(osVersion);
- if (opts.has(hashDependencies)) {
- options.dependenciesToHash = opts.valueOf(hashDependencies);
- // if storing hashes of dependencies then the module path is required
+ if (opts.has(hashModules)) {
+ options.modulesToHash = opts.valueOf(hashModules);
+ // if storing hashes then the module path is required
if (options.moduleFinder == null)
- throw new CommandException("err.modulepath.must.be.specified").showUsage(true);
+ throw new CommandException("err.modulepath.must.be.specified")
+ .showUsage(true);
}
- if (words.size() <= 1)
- throw new CommandException("err.jmod.must.be.specified").showUsage(true);
- Path path = Paths.get(words.get(1));
- if (options.mode.equals(Mode.CREATE) && Files.exists(path))
- throw new CommandException("err.file.already.exists", path);
- else if ((options.mode.equals(Mode.LIST) ||
- options.mode.equals(Mode.DESCRIBE))
- && Files.notExists(path))
- throw new CommandException("err.jmod.not.found", path);
- options.jmodFile = path;
+ if (options.mode.equals(Mode.HASH)) {
+ if (options.moduleFinder == null || options.modulesToHash == null)
+ throw new CommandException("err.modulepath.must.be.specified")
+ .showUsage(true);
+ } else {
+ if (words.size() <= 1)
+ throw new CommandException("err.jmod.must.be.specified").showUsage(true);
+ Path path = Paths.get(words.get(1));
- if (words.size() > 2)
- throw new CommandException("err.unknown.option",
- words.subList(2, words.size())).showUsage(true);
+ if (options.mode.equals(Mode.CREATE) && Files.exists(path))
+ throw new CommandException("err.file.already.exists", path);
+ else if ((options.mode.equals(Mode.LIST) ||
+ options.mode.equals(Mode.DESCRIBE))
+ && Files.notExists(path))
+ throw new CommandException("err.jmod.not.found", path);
+
+ if (options.dryrun) {
+ throw new CommandException("err.invalid.dryrun.option");
+ }
+ options.jmodFile = path;
+
+ if (words.size() > 2)
+ throw new CommandException("err.unknown.option",
+ words.subList(2, words.size())).showUsage(true);
+ }
if (options.mode.equals(Mode.CREATE) && options.classpath == null)
throw new CommandException("err.classpath.must.be.specified").showUsage(true);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Fri May 06 06:23:30 2016 -0700
@@ -1,9 +1,9 @@
main.usage.summary=\
-Usage: {0} (create|list|describe) <OPTIONS> <jmod-file>\n\
+Usage: {0} (create|list|describe|hash) <OPTIONS> <jmod-file>\n\
use --help for a list of possible options
main.usage=\
-Usage: {0} (create|list|describe) <OPTIONS> <jmod-file>
+Usage: {0} (create|list|describe|hash) <OPTIONS> <jmod-file>
error.prefix=Error:
warn.prefix=Warning:
@@ -14,6 +14,8 @@
\list - Prints the names of all the entries
main.opt.mode.describe=\
\describe - Prints the module details
+main.opt.mode.hash=\
+\hash - Records hashes of tied modules.
main.opt.help=Print this usage message
main.opt.version=Version information
@@ -21,9 +23,9 @@
main.opt.libs=Location of native libraries
main.opt.cmds=Location of native commands
main.opt.config=Location of user-editable config files
+main.opt.dry-run=Dry run of hash mode
main.opt.exclude=Exclude files, given as a PATTERN
main.opt.module-version= Module version
-main.opt.modulepath=Module path
main.opt.main-class=Main class
main.opt.main-class.arg=class-name
main.opt.os-name=Operating system name
@@ -32,18 +34,25 @@
main.opt.os-arch.arg=os-arch
main.opt.os-version=Operating system version
main.opt.os-version.arg=os-version
-main.opt.hash-dependencies=Compute and record hashes of dependencies matched by the pattern
+main.opt.modulepath=Module path
+main.opt.hash-modules=Compute and record hashes to tie a packaged module\
+\ with modules matching the given pattern and depending upon it directly\
+\ or indirectly. The hashes are recorded in the JMOD file being created, or\
+\ a JMOD file or modular JAR on the module path specified the jmod hash command.
+
main.opt.cmdfile=Read options from the specified file
-err.missing.mode=one of create, list, or describe must be specified
-err.invalid.mode=mode must be one of create, list, or describe: {0}
+module.hashes.recorded=Hashes are recorded in module {0}
+
+err.missing.mode=one of create, list, describe, or hash must be specified
+err.invalid.mode=mode must be one of create, list, describe, or hash: {0}
err.classpath.must.be.specified=--class-path must be specified
err.jmod.must.be.specified=jmod-file must be specified
err.invalid.version=invalid module version {0}
-err.output.must.be.specified:--output must be specified
-err.mods.must.be.specified:--mods must be specified
-err.modulepath.must.be.specified:--module-path must be specified when hashing dependencies
-err.invalid.main-class:invalid main-class name: {0}
+err.output.must.be.specified=--output must be specified
+err.mods.must.be.specified=--mods must be specified
+err.modulepath.must.be.specified=--module-path must be specified when hashing modules
+err.invalid.main-class=invalid main-class name: {0}
err.path.not.found=path not found: {0}
err.path.not.valid=invalid path: {0}
err.path.not.a.dir=path must be a directory: {0}
@@ -54,5 +63,9 @@
err.unknown.option=unknown option(s): {0}
err.missing.arg=no value given for {0}
err.internal.error=internal error: {0} {1} {2}
+err.invalid.dryrun.option=--dry-run can only be used with hash mode
err.module.descriptor.not.found=Module descriptor not found
warn.invalid.arg=Invalid classname or pathname not exist: {0}
+warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0}
+warn.module.resolution.fail=No hashes recorded: {0}
+
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java Fri May 06 06:23:30 2016 -0700
@@ -46,7 +46,7 @@
Class<?> c = Class.forName(LocaleDataProvider.class.getModule(), bundleName);
if (c != null && ResourceBundle.class.isAssignableFrom(c)) {
try {
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"unchecked", "deprecation"})
ResourceBundle rb = ((Class<ResourceBundle>) c).newInstance();
return rb;
} catch (InstantiationException | IllegalAccessException e) {
--- a/jdk/test/ProblemList.txt Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/ProblemList.txt Fri May 06 06:23:30 2016 -0700
@@ -319,6 +319,8 @@
tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all
+tools/pack200/Pack200Props.java 8155857 generic-all
+
############################################################################
# jdk_jdi
--- a/jdk/test/TEST.ROOT Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/TEST.ROOT Fri May 06 06:23:30 2016 -0700
@@ -26,9 +26,12 @@
# Allow querying of sun.arch.data.model in @requires clauses
requires.properties=sun.arch.data.model
-# Tests using jtreg 4.2 b01 features
-requiredVersion=4.2 b01
+# Tests using jtreg 4.2 b02 features
+requiredVersion=4.2 b02
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
external.lib.roots = ../../
+
+# Use new form of -Xpatch
+useNewXpatch=true
--- a/jdk/test/TEST.groups Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/TEST.groups Fri May 06 06:23:30 2016 -0700
@@ -29,7 +29,6 @@
:jdk_lang \
-java/lang/ProcessHandle/TreeTest.java \
:jdk_util \
- -java/util/WeakHashMap/GCDuringIteration.java \
-java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
-java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
sun/nio/cs/ISO8859x.java \
@@ -39,7 +38,6 @@
tier2 = \
java/lang/ProcessHandle/TreeTest.java \
- java/util/WeakHashMap/GCDuringIteration.java \
java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
:jdk_io \
--- a/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh Fri May 06 06:23:30 2016 -0700
@@ -81,9 +81,9 @@
chmod -fR 777 bug
-${COMPILEJAVA}${FS}bin${FS}javac -d . bug${FS}*.java
+${COMPILEJAVA}${FS}bin${FS}javac -addmods java.corba -d . bug${FS}*.java
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp . bug/JavaBug > test.out 2>&1
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -addmods java.corba -cp . bug/JavaBug > test.out 2>&1
grep "NullPointerException" test.out
--- a/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java Fri May 06 06:23:30 2016 -0700
@@ -27,7 +27,8 @@
* @summary Four helper classes missing in Sun JDK
* @library /lib/testlibrary
* @build jdk.testlibrary.*
- * @run main CorbaExceptionsCompileTest
+ * @compile -addmods java.corba CorbaExceptionsCompileTest.java
+ * @run main/othervm -addmods java.corba CorbaExceptionsCompileTest
*/
import java.io.*;
--- a/jdk/test/com/sun/corba/se/impl/io/HookPutFieldsTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/com/sun/corba/se/impl/io/HookPutFieldsTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,6 +25,8 @@
* @test
* @bug 7095856
* @summary OutputStreamHook doesn't handle null values
+ * @compile -addmods java.corba HookPutFieldsTest.java
+ * @run main/othervm -addmods java.corba HookPutFieldsTest
*/
import java.net.InetAddress;
--- a/jdk/test/com/sun/corba/se/impl/orb/SetDefaultORBTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/com/sun/corba/se/impl/orb/SetDefaultORBTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,8 @@
* @test
* @bug 8028215
* @summary SetDefaultORBTest setting ORB impl via properties test
- * @run main/othervm SetDefaultORBTest
+ * @compile -addmods java.corba SetDefaultORBTest.java
+ * @run main/othervm -addmods java.corba SetDefaultORBTest
*
*/
--- a/jdk/test/com/sun/net/httpserver/bugs/B6373555.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/com/sun/net/httpserver/bugs/B6373555.java Fri May 06 06:23:30 2016 -0700
@@ -29,7 +29,6 @@
import java.net.*;
import java.io.*;
-import javax.xml.soap.*;
import java.util.*;
import com.sun.net.httpserver.*;
import java.util.concurrent.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/Cause/FocusCauseTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,224 @@
+/*
+ * 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 8080395
+ @summary consider making sun.awt.CausedFocusEvent functionality public
+ @run main FocusCauseTest
+*/
+
+
+import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.lang.IllegalArgumentException;
+import java.lang.Override;
+import java.lang.RuntimeException;
+import java.util.Arrays;
+
+public class FocusCauseTest {
+
+ private static Cause[] causes1 = {Cause.ACTIVATION,
+ Cause.UNKNOWN, Cause.UNKNOWN, Cause.TRAVERSAL_FORWARD,
+ Cause.TRAVERSAL_FORWARD, Cause.TRAVERSAL_BACKWARD,
+ Cause.TRAVERSAL_BACKWARD, Cause.TRAVERSAL_UP,
+ Cause.TRAVERSAL_DOWN, Cause.CLEAR_GLOBAL_FOCUS_OWNER};
+ private static Cause[] causes2 = new Cause[10];
+ private static int cnt;
+
+ static byte[] data =
+ {-84, -19, 0, 5, 115, 114, 0, 24, 115, 117, 110, 46, 97, 119,
+ 116, 46, 67, 97, 117, 115, 101, 100, 70, 111, 99, 117, 115, 69, 118,
+ 101, 110, 116, -51, 98, 39, -75, 86, 52, 107, 30, 2, 0, 1, 76, 0, 5,
+ 99, 97, 117, 115, 101, 116, 0, 32, 76, 115, 117, 110, 47, 97, 119,
+ 116, 47, 67, 97, 117, 115, 101, 100, 70, 111, 99, 117, 115, 69, 118,
+ 101, 110, 116, 36, 67, 97, 117, 115, 101, 59, 120, 114, 0, 25, 106,
+ 97, 118, 97, 46, 97, 119, 116, 46, 101, 118, 101, 110, 116, 46, 70,
+ 111, 99, 117, 115, 69, 118, 101, 110, 116, 7, 68, -65, 75, 55, -113,
+ 98, -52, 2, 0, 1, 90, 0, 9, 116, 101, 109, 112, 111, 114, 97, 114,
+ 121, 120, 114, 0, 29, 106, 97, 118, 97, 46, 97, 119, 116, 46, 101,
+ 118, 101, 110, 116, 46, 67, 111, 109, 112, 111, 110, 101, 110, 116,
+ 69, 118, 101, 110, 116, 112, 109, -6, -107, 79, -87, -38, 69, 2, 0,
+ 0, 120, 114, 0, 17, 106, 97, 118, 97, 46, 97, 119, 116, 46, 65, 87,
+ 84, 69, 118, 101, 110, 116, -26, -85, 45, -31, 24, -33, -118, -61,
+ 2, 0, 3, 90, 0, 8, 99, 111, 110, 115, 117, 109, 101, 100, 73, 0, 2,
+ 105, 100, 91, 0, 5, 98, 100, 97, 116, 97, 116, 0, 2, 91, 66, 120,
+ 114, 0, 21, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 69, 118,
+ 101, 110, 116, 79, 98, 106, 101, 99, 116, 76, -115, 9, 78, 24, 109,
+ 125, -88, 2, 0, 0, 120, 112, 0, 0, 0, 3, -20, 112, 0, 126, 114, 0,
+ 30, 115, 117, 110, 46, 97, 119, 116, 46, 67, 97, 117, 115, 101, 100,
+ 70, 111, 99, 117, 115, 69, 118, 101, 110, 116, 36, 67, 97, 117, 115,
+ 101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 120, 114, 0, 14, 106, 97,
+ 118, 97, 46, 108, 97, 110, 103, 46, 69, 110, 117, 109, 0, 0, 0, 0,
+ 0, 0, 0, 0, 18, 0, 0, 120, 112, 116, 0};
+
+ static byte[] dataOld =
+ {-84, -19, 0, 5, 115, 114, 0, 25, 106, 97, 118, 97, 46, 97, 119,
+ 116, 46, 101, 118, 101, 110, 116, 46, 70, 111, 99, 117, 115, 69,
+ 118, 101, 110, 116, 7, 68, -65, 75, 55, -113, 98, -52, 2, 0, 1, 90,
+ 0, 9, 116, 101, 109, 112, 111, 114, 97, 114, 121, 120, 114, 0, 29,
+ 106, 97, 118, 97, 46, 97, 119, 116, 46, 101, 118, 101, 110, 116, 46,
+ 67, 111, 109, 112, 111, 110, 101, 110, 116, 69, 118, 101, 110, 116,
+ 112, 109, -6, -107, 79, -87, -38, 69, 2, 0, 0, 120, 114, 0, 17, 106,
+ 97, 118, 97, 46, 97, 119, 116, 46, 65, 87, 84, 69, 118, 101, 110,
+ 116, -26, -85, 45, -31, 24, -33, -118, -61, 2, 0, 3, 90, 0, 8, 99,
+ 111, 110, 115, 117, 109, 101, 100, 73, 0, 2, 105, 100, 91, 0, 5, 98,
+ 100, 97, 116, 97, 116, 0, 2, 91, 66, 120, 114, 0, 21, 106, 97, 118,
+ 97, 46, 117, 116, 105, 108, 46, 69, 118, 101, 110, 116, 79, 98, 106,
+ 101, 99, 116, 76, -115, 9, 78, 24, 109, 125, -88, 2, 0, 0, 120, 112,
+ 0, 0, 0, 0, 100, 112, 0};
+
+ static String[] causesIn = {"UNKNOWN", "MOUSE_EVENT", "TRAVERSAL",
+ "TRAVERSAL_UP", "TRAVERSAL_DOWN", "TRAVERSAL_FORWARD",
+ "TRAVERSAL_BACKWARD", "MANUAL_REQUEST", "AUTOMATIC_TRAVERSE"
+ ,"ROLLBACK", "NATIVE_SYSTEM", "ACTIVATION",
+ "CLEAR_GLOBAL_FOCUS_OWNER", "RETARGETED"};
+
+ static FocusEvent.Cause[] causesOut = {FocusEvent.Cause.UNKNOWN,
+ FocusEvent.Cause.MOUSE_EVENT,
+ FocusEvent.Cause.TRAVERSAL, FocusEvent.Cause.TRAVERSAL_UP,
+ FocusEvent.Cause.TRAVERSAL_DOWN, FocusEvent.Cause.TRAVERSAL_FORWARD,
+ FocusEvent.Cause.TRAVERSAL_BACKWARD, FocusEvent.Cause.UNKNOWN,
+ FocusEvent.Cause.UNKNOWN, FocusEvent.Cause.ROLLBACK,
+ FocusEvent.Cause.UNEXPECTED, FocusEvent.Cause.ACTIVATION,
+ FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER, FocusEvent.Cause.UNKNOWN
+ };
+
+ public static void main(String[] args) throws Exception {
+ testCauses();
+ testNullCause();
+ testCausedFocusEventDeserialization();
+ testFocusEventDeserialization();
+ System.out.println("ok");
+ }
+
+ private static void testNullCause() {
+ try {
+ new FocusEvent(new Frame(), FocusEvent.FOCUS_GAINED, true,
+ null, null);
+ throw new RuntimeException("Exception is not thrown when the " +
+ "cause is null");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ private static void testCauses() throws Exception {
+ cnt = 0;
+ Frame frame = new Frame();
+ TextField comp1 = new TextField();
+ comp1.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ System.out.println(e.getCause());
+ causes2[cnt++] = e.getCause();
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ System.out.println(e.getCause());
+ causes2[cnt++] = e.getCause();
+ }
+ });
+ TextField comp2 = new TextField();
+ comp2.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ System.out.println(e.getCause());
+ causes2[cnt++] = e.getCause();
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ System.out.println(e.getCause());
+ causes2[cnt++] = e.getCause();
+ }
+ });
+ frame.add(comp1, BorderLayout.NORTH);
+ frame.add(comp2, BorderLayout.SOUTH);
+ frame.setVisible(true);
+
+ Robot robot = new Robot();
+ robot.delay(200);
+ robot.waitForIdle();
+ comp2.requestFocus();
+ robot.waitForIdle();
+ comp2.transferFocus();
+ robot.waitForIdle();
+ comp1.transferFocusBackward();
+ robot.waitForIdle();
+ comp2.transferFocusUpCycle();
+ robot.waitForIdle();
+ frame.transferFocusDownCycle();
+ robot.waitForIdle();
+ frame.dispose();
+ robot.waitForIdle();
+ if (!Arrays.equals(causes1, causes2)) {
+ throw new RuntimeException("wrong cause " + causes2);
+ }
+ }
+
+ private static void testCausedFocusEventDeserialization() throws
+ Exception {
+ for (int i = 0; i < causesIn.length; i++) {
+ final String causeIn = causesIn[i];
+ ObjectInputStream oi = new ObjectInputStream(new InputStream() {
+ int cnt = 0;
+ @Override
+ public int read() throws IOException {
+ if(cnt < data.length) {
+ return data[cnt++];
+ } else if(cnt == data.length){
+ cnt++;
+ return causeIn.length();
+ } else if(cnt - data.length - 1 < causeIn.length()) {
+ return causeIn.getBytes()[cnt++ - data.length - 1];
+ }
+ return -1;
+ }
+ });
+ FocusEvent ev = (FocusEvent) oi.readObject();
+ System.out.println(ev);
+ if(ev.getCause() != causesOut[i]) {
+ throw new RuntimeException("Wrong cause read :" +ev.getCause());
+ }
+ }
+ }
+
+ private static void testFocusEventDeserialization() throws
+ Exception {
+ ObjectInputStream oi = new ObjectInputStream(
+ new ByteArrayInputStream(dataOld));
+ FocusEvent ev = (FocusEvent)oi.readObject();
+ if(ev.getCause() != FocusEvent.Cause.UNKNOWN) {
+ throw new RuntimeException("Wrong cause in deserialized FocusEvent "
+ + ev.getCause());
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/PrintJob/NullFrameTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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 8154057
+ * @summary getPrintJob doesn't throw NPE if frame is null
+ * @run main NullFrameTest
+ */
+import java.awt.JobAttributes;
+import java.awt.Toolkit;
+
+public class NullFrameTest {
+ public static void main(String[] args) {
+ JobAttributes ja = new JobAttributes();
+ ja.setDialog(JobAttributes.DialogType.COMMON);
+ boolean npeThrown = false;
+ try {
+ Toolkit.getDefaultToolkit().getPrintJob(null,
+ "test Printing", ja, null);
+ } catch (NullPointerException ex) {
+ npeThrown = true;
+ }
+ if (!npeThrown) {
+ throw
+ new RuntimeException("getPrintJob didn't throw NPE for null Frame");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/TrayIcon/UpdatePopupMenu/UpdatePopupMenu.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,233 @@
+/*
+ * 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 8147841
+ @summary Updating Tray Icon popup menu does not update menu items on Mac OS X
+ @run main/manual UpdatePopupMenu
+ */
+
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
+import java.awt.PopupMenu;
+import java.awt.MenuItem;
+import java.awt.Image;
+import java.awt.Graphics2D;
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+import java.awt.RenderingHints;
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class UpdatePopupMenu implements ActionListener {
+
+ private static final int imageSize = 32;
+ private static final int imageInset = 4;
+ private static GridBagLayout layout;
+ private static Panel mainControlPanel;
+ private static Panel resultButtonPanel;
+ private static TextArea instructionTextArea;
+ private static Button passButton;
+ private static Button failButton;
+ private static Frame mainFrame;
+ private static Thread mainThread = null;
+ private static boolean testPassed = false;
+ private static boolean isInterrupted = false;
+ private static final int testTimeOut = 300000;
+
+ private Image createSystemTrayIconImage() {
+ final BufferedImage trayImage = new BufferedImage(
+ imageSize,
+ imageSize,
+ BufferedImage.TYPE_INT_ARGB);
+
+ final Graphics2D imageGraphics = (Graphics2D) trayImage.getGraphics();
+
+ imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ imageGraphics.setColor(new Color(255, 255, 255, 0));
+ imageGraphics.fillRect(0, 0, trayImage.getWidth(),
+ trayImage.getHeight());
+
+ imageGraphics.setColor(Color.green);
+
+ int imageWidth = trayImage.getWidth() - 2 * imageInset;
+ int imageHeight = trayImage.getHeight() - 2 * imageInset;
+
+ imageGraphics.fillOval(imageInset, imageInset, imageWidth, imageHeight);
+ imageGraphics.setColor(Color.darkGray);
+ imageGraphics.drawOval(imageInset, imageInset, imageWidth, imageHeight);
+
+ return trayImage;
+ }
+
+ private PopupMenu createPopupMenu(final TrayIcon trayIcon,
+ final int menuCount) {
+
+ final PopupMenu trayIconPopupMenu = new PopupMenu();
+
+ for (int i = 1; i <= menuCount; ++i) {
+ final MenuItem popupMenuItem = new MenuItem("MenuItem_" + i);
+
+ popupMenuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent ae) {
+ trayIcon.setPopupMenu(createPopupMenu(trayIcon,
+ menuCount + 1));
+ }
+ });
+
+ trayIconPopupMenu.add(popupMenuItem);
+ }
+
+ return trayIconPopupMenu;
+ }
+
+ private void createSystemTrayIcons() {
+
+ final TrayIcon trayIcon = new TrayIcon(createSystemTrayIconImage());
+ trayIcon.setImageAutoSize(true);
+ trayIcon.setToolTip("Update Popup Menu items");
+
+ try {
+ trayIcon.setPopupMenu(createPopupMenu(trayIcon, 2));
+ SystemTray.getSystemTray().add(trayIcon);
+
+ } catch (AWTException ex) {
+ throw new RuntimeException("System Tray cration failed");
+ }
+ }
+
+ private void createInstructionUI() {
+ mainFrame = new Frame("Updating TrayIcon Popup Menu Item Test");
+ layout = new GridBagLayout();
+ mainControlPanel = new Panel(layout);
+ resultButtonPanel = new Panel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ String instructions
+ = "INSTRUCTIONS:"
+ + "\n 1. Click on the System Tray Icon"
+ + "\n 2. Click on any of the displayed Menu items"
+ + "\n 3. Repeat step 1 and count the number of items in the "
+ + "Menu"
+ + "\n 4. The number of items in the Menu should increase by 1"
+ + "\n 5. Repeating steps 1, 2 and 3 should not break 4th step"
+ + "\n 6. Click Fail if the 4th step is broken, Otherwise "
+ + "click Pass ";
+
+ instructionTextArea = new TextArea();
+ instructionTextArea.setText(instructions);
+ instructionTextArea.setEnabled(false);
+ instructionTextArea.setBackground(Color.white);
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ passButton = new Button("Pass");
+ passButton.setName("Pass");
+ passButton.addActionListener(this);
+
+ failButton = new Button("Fail");
+ failButton.setName("Fail");
+ failButton.addActionListener(this);
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+ mainFrame.setVisible(true);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ if (ae.getSource() instanceof Button) {
+ Button btn = (Button) ae.getSource();
+ switch (btn.getName()) {
+ case "Pass":
+ testPassed = true;
+ isInterrupted = true;
+ mainThread.interrupt();
+ break;
+
+ case "Fail":
+ testPassed = false;
+ isInterrupted = true;
+ mainThread.interrupt();
+ break;
+ }
+ }
+ }
+
+ private static void cleanUp() {
+ mainFrame.dispose();
+ }
+
+ public static void main(final String[] args) throws Exception {
+ if (SystemTray.isSupported()) {
+
+ UpdatePopupMenu updatePopupMenu = new UpdatePopupMenu();
+ updatePopupMenu.createInstructionUI();
+ updatePopupMenu.createSystemTrayIcons();
+
+ mainThread = Thread.currentThread();
+ try {
+ mainThread.sleep(testTimeOut);
+ } catch (InterruptedException ex) {
+ if (!testPassed) {
+ throw new RuntimeException("Updating TrayIcon popup menu"
+ + " items FAILED");
+ }
+ } finally {
+ cleanUp();
+ }
+
+ if (!isInterrupted) {
+ throw new RuntimeException("Test Timed out after "
+ + testTimeOut / 1000 + " seconds");
+ }
+
+ } else {
+ System.out.println("System Tray is not supported on this platform");
+ }
+ }
+}
--- a/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,17 +56,24 @@
}
});
- Util.waitForIdle(null);
+ Robot testRobot = null;
try {
- Point loc = textArea.getLocationOnScreen();
- Util.drag(new Robot(),
- new Point((int) loc.x + 3, (int) loc.y + 3),
- new Point((int) loc.x + 40, (int) loc.y + 40),
- InputEvent.BUTTON1_MASK);
- } catch (AWTException ex) {
- throw new RuntimeException("Could not initiate a drag operation");
+ testRobot = new Robot();
+ } catch(AWTException ex) {
+ throw new RuntimeException("Error while creating Robot");
}
- Util.waitForIdle(null);
+
+ Util.waitForIdle(testRobot);
+
+ Point loc = textArea.getLocationOnScreen();
+ Util.drag(testRobot,
+ new Point((int) loc.x + 3, (int) loc.y + 3),
+ new Point((int) loc.x + 40, (int) loc.y + 40),
+ InputEvent.BUTTON1_MASK);
+
+ Util.waitForIdle(testRobot);
+
+ testRobot.delay(200);
}
private static void constructTestUI() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/DummyPrintTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,247 @@
+/*
+ * 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 6921664
+ * @summary Verifies number of copies and the job name are passed to a
+ * 3rd party PrintService.
+ * @run main DummyPrintTest
+ */
+import java.awt.Graphics;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.util.HashSet;
+import java.util.Set;
+import javax.print.Doc;
+import javax.print.DocFlavor;
+import javax.print.DocPrintJob;
+import javax.print.PrintException;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.print.ServiceUIFactory;
+import javax.print.attribute.Attribute;
+import javax.print.attribute.AttributeSet;
+import javax.print.attribute.HashPrintJobAttributeSet;
+import javax.print.attribute.HashPrintServiceAttributeSet;
+import javax.print.attribute.PrintJobAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.PrintServiceAttribute;
+import javax.print.attribute.PrintServiceAttributeSet;
+import javax.print.attribute.standard.Copies;
+import javax.print.attribute.standard.JobName;
+import javax.print.attribute.standard.PrinterName;
+import javax.print.attribute.standard.PrinterState;
+import javax.print.event.PrintJobAttributeListener;
+import javax.print.event.PrintJobListener;
+import javax.print.event.PrintServiceAttributeListener;
+
+
+public class DummyPrintTest {
+
+ public static void main(String[] args) throws Exception {
+ // register custom print service implementation
+ String printerName = "myDummyPrintService";
+ PrintServiceLookup.registerService(new DummyPrintService(printerName));
+ // calling third party print logic
+ thirdPartyPrintLogic(printerName);
+ }
+
+ static void thirdPartyPrintLogic(String printerName) throws Exception {
+ PrinterJob printerjob = PrinterJob.getPrinterJob();
+ printerjob.setCopies(2);
+ printerjob.setJobName("myJobName");
+ printerjob.setPrintable(new DummyPrintable());
+ for (PrintService printService : PrinterJob.lookupPrintServices()) {
+ System.out.println("check printer name of service " + printService);
+ if (printerName.equals(printService.getName())) {
+ System.out.println("correct printer service do print...");
+ printerjob.setPrintService(printService);
+ printerjob.print();
+ break;
+ }
+ }
+ }
+}
+
+class DummyPrintService implements PrintService {
+ private final String _name;
+ private final Set<DocFlavor> _supportedFlavors;
+ private final PrintServiceAttributeSet _printServiceAttributeSet;
+
+ public DummyPrintService(String name) {
+ _name = name;
+ _supportedFlavors = new HashSet<DocFlavor>();
+ _supportedFlavors.add(DocFlavor.SERVICE_FORMATTED.PAGEABLE);
+ _supportedFlavors.add(DocFlavor.SERVICE_FORMATTED.PRINTABLE);
+ _printServiceAttributeSet = new HashPrintServiceAttributeSet();
+ _printServiceAttributeSet.add(new PrinterName(name, null));
+ _printServiceAttributeSet.add(PrinterState.IDLE);
+ }
+
+ @Override
+ public String toString() {
+ return "Dummy Printer : " + getName();
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ @Override
+ public DocPrintJob createPrintJob() {
+ return new DummyDocPrintJob(this);
+ }
+
+ @Override
+ public boolean isDocFlavorSupported(DocFlavor flavor) {
+ return _supportedFlavors.contains(flavor);
+ }
+
+ @Override
+ public <T extends PrintServiceAttribute> T getAttribute(Class<T> category) {
+ return category.cast(_printServiceAttributeSet.get(category));
+ }
+
+ @Override
+ public PrintServiceAttributeSet getAttributes() {
+ return _printServiceAttributeSet;
+ }
+
+ @Override
+ public DocFlavor[] getSupportedDocFlavors() {
+ return _supportedFlavors.toArray(new DocFlavor[_supportedFlavors.size()]);
+ }
+
+ @Override
+ public Object getDefaultAttributeValue(Class<? extends Attribute> category) {
+ return null;
+ }
+
+ @Override
+ public ServiceUIFactory getServiceUIFactory() {
+ return null;
+ }
+
+ @Override
+ public Class<?>[] getSupportedAttributeCategories() {
+ return null;
+ }
+
+ @Override
+ public Object getSupportedAttributeValues(Class<? extends Attribute> category,
+ DocFlavor flavor, AttributeSet attributes) {
+ return null;
+ }
+
+ @Override
+ public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
+ AttributeSet attributes) {
+ return null;
+ }
+
+ @Override
+ public boolean isAttributeCategorySupported(Class<? extends Attribute> category) {
+ return false;
+ }
+
+ @Override
+ public boolean isAttributeValueSupported(Attribute attrval,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return false;
+ }
+
+ @Override
+ public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener) {
+ }
+
+ @Override
+ public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener) {
+ }
+}
+
+class DummyDocPrintJob implements DocPrintJob {
+ private static int _counter;
+ private final PrintService _printService;
+ private final PrintJobAttributeSet _printJobAttributeSet;
+
+ public DummyDocPrintJob(PrintService printService) {
+ _counter++;
+ _printService = printService;
+ _printJobAttributeSet = new HashPrintJobAttributeSet();
+ }
+
+ @Override
+ public PrintService getPrintService() {
+ return _printService;
+ }
+
+ @Override
+ public PrintJobAttributeSet getAttributes() {
+ return _printJobAttributeSet;
+ }
+
+ @Override
+ public void addPrintJobAttributeListener(PrintJobAttributeListener listener,
+ PrintJobAttributeSet printJobAttributeSet) {
+ }
+
+ @Override
+ public void removePrintJobAttributeListener(PrintJobAttributeListener listener) {
+ }
+
+ @Override
+ public void addPrintJobListener(PrintJobListener listener) {
+ }
+
+ @Override
+ public void removePrintJobListener(PrintJobListener listener) {
+ }
+
+ @Override
+ public void print(Doc doc,
+ PrintRequestAttributeSet printRequestAttributeSet)
+ throws PrintException {
+ System.out.println("job name: " + printRequestAttributeSet.get(JobName.class));
+ System.out.println("copies: " + printRequestAttributeSet.get(Copies.class));
+ if(printRequestAttributeSet.get(JobName.class) == null ||
+ printRequestAttributeSet.get(Copies.class) == null) {
+ throw new RuntimeException("Copies and JobName is not passed correctly");
+ }
+ }
+}
+
+class DummyPrintable implements Printable {
+ @Override
+ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
+ throws PrinterException {
+ if (pageIndex == 0) {
+ return Printable.PAGE_EXISTS;
+ } else {
+ return Printable.NO_SUCH_PAGE;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 6197099
+ * @summary Verifies PrinterJob's getUserName() throws a security exception when
+ * username permission is not given
+ * @run main/othervm/java.security.policy=GetUserNameTest.policy GetUserNameTest
+ */
+import java.awt.print.PrinterJob;
+
+public class GetUserNameTest {
+
+ public static void main(String args[]) {
+ System.setSecurityManager(new SecurityManager());
+ PrinterJob pj = PrinterJob.getPrinterJob();
+ boolean secExcpn = false;
+ try {
+ System.out.println(pj.getUserName());
+ } catch (SecurityException ex) {
+ secExcpn = true;
+ System.out.println("SecurityException thrown as user.name permission "
+ + "not given");
+ }
+ if (!secExcpn) {
+ throw new RuntimeException("SecurityException not thrown");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.policy Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+grant {
+ permission java.lang.RuntimePermission "setSecurityManager";
+ permission java.lang.RuntimePermission "createSecurityManager";
+ permission java.lang.RuntimePermission "usePolicy";
+ permission java.lang.RuntimePermission "queuePrintJob";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PageDialogMarginTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,92 @@
+/*
+ * 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 6801613
+ * @summary Verifies if cross-platform pageDialog and printDialog top margin
+ * entry is working
+ * @run main/manual PageDialogMarginTest
+ */
+import java.awt.Component;
+import java.awt.print.PageFormat;
+import java.awt.print.PrinterJob;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.standard.MediaPrintableArea;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+public class PageDialogMarginTest {
+
+ public static void main(String args[]) throws Exception {
+ String[] instructions
+ = {
+ "Page Dialog will be shown.",
+ "Change top(in) margin value from 1.0 to 2.0",
+ "Then select OK."
+ };
+ SwingUtilities.invokeAndWait(() -> {
+ JOptionPane.showMessageDialog((Component) null,
+ instructions, "Instructions",
+ JOptionPane.INFORMATION_MESSAGE);
+ });
+ PrinterJob pj = PrinterJob.getPrinterJob();
+ try {
+ HashPrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+ PageFormat pf;
+ pf = pj.pageDialog(aset);
+ double left = pf.getImageableX();
+ double top = pf.getImageableY();
+ System.out.println("pageDialog - left/top from pageFormat: " + left / 72
+ + " " + top / 72);
+ System.out.println("pageDialog - left/top from attribute set: "
+ + getPrintableXFromASet(aset) + " "
+ + getPrintableYFromASet(aset));
+ if (top / 72 != 2.0f || getPrintableYFromASet(aset) != 2.0f) {
+ throw new RuntimeException("Top margin value not updated");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static double getPrintableXFromASet(PrintRequestAttributeSet aset) {
+ try {
+ return ((MediaPrintableArea) aset.get(
+ MediaPrintableArea.class)).getX(MediaPrintableArea.INCH);
+ } catch (Exception e) {
+ return -1.0;
+ }
+ }
+
+ static double getPrintableYFromASet(PrintRequestAttributeSet aset) {
+ try {
+ return ((MediaPrintableArea) aset.get(
+ MediaPrintableArea.class)).getY(MediaPrintableArea.INCH);
+ } catch (Exception e) {
+ return -1.0;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,867 @@
+/*
+ * 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.beans.BeanInfo;
+import java.beans.BeanProperty;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyDescriptor;
+
+import java.util.Arrays;
+
+
+/**
+ * @test
+ * @bug 8132973 8132732 8155013
+ * @summary Some check for BeanProperty annotation
+ * @author a.stepanov
+ * @run main AnonymousClassBeanPropertyTest
+ */
+
+
+public class AnonymousClassBeanPropertyTest {
+
+ private final static String DESCRIPTION = "TEST";
+ private final static boolean BOUND = true;
+ private final static boolean EXPERT = false;
+ private final static boolean HIDDEN = true;
+ private final static boolean PREFERRED = false;
+ private final static boolean REQUIRED = true;
+ private final static boolean UPDATE = false;
+
+ private final static double X = java.lang.Math.PI;
+
+ private final static String
+ V_NAME = "java.lang.Math.PI",
+ V_SHORT = "PI",
+ V = Double.toString(X);
+
+ private final static String DESCRIPTION_2 = "XYZ";
+
+
+ // ---------- test cases (interfaces) ----------
+
+ private interface IGet {
+ double getX();
+ }
+
+ private interface ISet {
+ void setX(double v);
+ }
+
+ private interface IGetByIndex {
+ double getX(int i);
+ }
+
+ private interface ISetByIndex {
+ void setX(int i, double v);
+ }
+
+ private interface IGetArray {
+ double[] getX();
+ }
+
+ private interface ISetArray {
+ void setX(double a[]);
+ }
+
+ private interface IGetBoth {
+ double getX(int i);
+ double[] getX();
+ }
+
+ private interface ISetBoth {
+ void setX(int i, double v);
+ void setX(double a[]);
+ }
+
+ private interface IGetSet {
+ double getX();
+ void setX(double v);
+ }
+
+ private interface IGetSetByIndex {
+ double getX(int i);
+ void setX(int i, double v);
+ }
+
+ private interface IGetSetBoth {
+ double getX(int i);
+ double[] getX();
+ void setX(int i, double v);
+ void setX(double a[]);
+ }
+
+
+ // ---------- checks ----------
+
+ private static boolean check(String what, boolean v, boolean ref) {
+
+ boolean ok = (v == ref);
+ if (!ok) { System.out.println(
+ "invalid " + what + ": " + v + ", expected: " + ref); }
+ return ok;
+ }
+
+ private static boolean checkInfo(Class<?> c, String what) {
+
+ BeanInfo i;
+ try { i = Introspector.getBeanInfo(c, Object.class); }
+ catch (IntrospectionException e) { throw new RuntimeException(e); }
+
+ System.out.println("\nchecking info for " + what);
+
+ PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+ int nd = descriptors.length;
+ if (nd != 1) {
+ System.out.println("invalid number of descriptors: " + nd);
+ return false;
+ }
+
+ PropertyDescriptor d = descriptors[0];
+
+ String descr = d.getShortDescription();
+ boolean ok = descr.equals(DESCRIPTION);
+ if (!ok) { System.out.println("invalid description: " + descr +
+ ", expected: " + DESCRIPTION); }
+
+ ok &= check("isBound", d.isBound(), BOUND);
+ ok &= check("isExpert", d.isExpert(), EXPERT);
+ ok &= check("isHidden", d.isHidden(), HIDDEN);
+ ok &= check("isPreferred", d.isPreferred(), PREFERRED);
+ ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
+ ok &= check("visualUpdate",
+ (boolean) d.getValue("visualUpdate"), UPDATE);
+
+ Object vals[] = (Object[]) d.getValue("enumerationValues");
+ if (vals == null) {
+ System.out.println("null enumerationValues");
+ return false;
+ }
+
+ if (vals.length == 0) {
+ System.out.println("empty enumerationValues");
+ return false;
+ }
+
+ boolean okVals = (
+ (vals.length == 3) &&
+ vals[0].toString().equals(V_SHORT) &&
+ vals[1].toString().equals(V) &&
+ vals[2].toString().equals(V_NAME));
+
+ if (!okVals) {
+ System.out.println("invalid enumerationValues:");
+ for (Object v: vals) { System.out.println(v.toString()); }
+ }
+
+ return (ok && okVals);
+ }
+
+ private static boolean checkAlternativeInfo(Class<?> c, String what) {
+
+ BeanInfo i;
+ try { i = Introspector.getBeanInfo(c, Object.class); }
+ catch (IntrospectionException e) { throw new RuntimeException(e); }
+
+ System.out.println("checking alternative info for " + what);
+
+ PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+ int nd = descriptors.length;
+ if (nd != 1) {
+ System.out.println("invalid number of descriptors: " + nd);
+ return false;
+ }
+
+ PropertyDescriptor d = descriptors[0];
+
+ String descr = d.getShortDescription();
+ boolean ok = descr.equals(DESCRIPTION_2);
+ if (!ok) { System.out.println("invalid alternative description: " +
+ descr + ", expected: " + DESCRIPTION_2); }
+
+ ok &= check("isBound", d.isBound(), !BOUND);
+ ok &= check("isExpert", d.isExpert(), !EXPERT);
+ ok &= check("isHidden", d.isHidden(), !HIDDEN);
+ ok &= check("isPreferred", d.isPreferred(), !PREFERRED);
+ ok &= check("required", (boolean) d.getValue("required"), !REQUIRED);
+ ok &= check("visualUpdate",
+ (boolean) d.getValue("visualUpdate"), !UPDATE);
+
+ Object vals[] = (Object[]) d.getValue("enumerationValues");
+ if (vals != null || vals.length > 0) {
+ System.out.println("non-empty enumerationValues");
+ return false;
+ }
+
+ return ok;
+ }
+
+
+
+ // ---------- run tests ----------
+
+ public static void main(String[] args) {
+
+ boolean passed = true, ok, ok2;
+
+ //----------------------------------------------------------------------
+
+ IGet testGet = new IGet() {
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX() { return X; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGet.getClass(), "IGet");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ //----------------------------------------------------------------------
+
+ ISet testSet = new ISet() {
+
+ private double x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(double v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testSet.getClass(), "ISet");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ //----------------------------------------------------------------------
+
+ IGetByIndex testGetByIndex = new IGetByIndex() {
+
+ private final double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX(int i) { return x[i]; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetByIndex.getClass(), "IGetByIndex");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ //----------------------------------------------------------------------
+
+ ISetByIndex testSetByIndex = new ISetByIndex() {
+
+ private final double x[] = {X, X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testSetByIndex.getClass(), "ISetByIndex");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ //----------------------------------------------------------------------
+
+ // TODO: please uncomment/update after 8155013 fix
+ /*
+ IGetArray testGetArray = new IGetArray() {
+
+ private final double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double[] getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetArray.getClass(), "IGetArray");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+ */
+
+ //----------------------------------------------------------------------
+
+ // TODO: please uncomment/update after 8155013 fix
+ /*
+ ISetArray testSetArray = new ISetArray() {
+
+ private double x[];
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(double a[]) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testSetArray.getClass(), "ISetArray");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+ */
+
+ //----------------------------------------------------------------------
+
+ IGetBoth testGetBoth_1 = new IGetBoth() {
+
+ private final double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX(int i) { return x[i]; }
+ @Override
+ public double[] getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetBoth_1.getClass(), "IGetBoth-1");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ // TODO: please uncomment/update after 8155013 fix
+ /*
+ IGetBoth testGetBoth_2 = new IGetBoth() {
+
+ private final double x[] = {X, X};
+
+ @Override
+ public double getX(int i) { return x[i]; }
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double[] getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetBoth_2.getClass(), "IGetBoth-2");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+ */
+
+ // TODO: please uncomment/update after 8132732 fix
+ /*
+ IGetBoth testGetBoth_3 = new IGetBoth() {
+
+ private final double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX(int i) { return x[i]; }
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ @Override
+ public double[] getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetBoth_3.getClass(), "IGetBoth-3");
+ System.out.println("OK = " + ok);
+ ok2 = checkAlternativeInfo(testGetBoth_3.getClass(), "IGetBoth-3");
+ System.out.println("OK = " + ok2);
+ passed = passed && ok && ok2;
+ */
+
+ //----------------------------------------------------------------------
+
+ ISetBoth testSetBoth_1 = new ISetBoth() {
+
+ private double x[] = new double[3];
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+ @Override
+ public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testSetBoth_1.getClass(), "ISetBoth-1");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ // TODO: please uncomment/update after 8155013 fix
+ /*
+ ISetBoth testSetBoth_2 = new ISetBoth() {
+
+ private double x[] = new double[3];
+
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testSetBoth_2.getClass(), "ISetBoth-2");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+ */
+
+ // TODO: please uncomment/update after 8132732 fix
+ /*
+ ISetBoth testSetBoth_3 = new ISetBoth() {
+
+ private double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ @Override
+ public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testSetBoth_3.getClass(), "ISetBoth-3");
+ System.out.println("OK = " + ok);
+ ok2 = checkAlternativeInfo(testSetBoth_3.getClass(), "ISetBoth-3");
+ System.out.println("OK = " + ok2);
+ passed = passed && ok && ok2;
+ */
+
+ //----------------------------------------------------------------------
+
+ IGetSet testGetSet_1 = new IGetSet() {
+
+ private double x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX() { return x; }
+ @Override
+ public void setX(double v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSet_1.getClass(), "IGetSet-1");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+
+ IGetSet testGetSet_2 = new IGetSet() {
+
+ private double x;
+
+ @Override
+ public double getX() { return x; }
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(double v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSet_2.getClass(), "IGetSet-2");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ // TODO: please uncomment/update after 8132973 fix
+ /*
+ IGetSet testGetSet_3 = new IGetSet() {
+
+ private double x;
+
+ @Override
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public double getX() { return x; }
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ @Override
+ public void setX(double v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSet_3.getClass(), "IGetSet-3");
+ System.out.println("OK = " + ok);
+ ok2 = checkAlternativeInfo(testGetSet_3.getClass(), "IGetSet-3");
+ System.out.println("OK = " + ok2);
+ passed = passed && ok && ok2;
+ */
+
+ //----------------------------------------------------------------------
+
+ IGetSetByIndex testGetSetByIndex_1 = new IGetSetByIndex() {
+
+ private final double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX(int i) { return x[i]; }
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSetByIndex_1.getClass(), "IGetSetByIndex-1");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+
+ IGetSetByIndex testGetSetByIndex_2 = new IGetSetByIndex() {
+
+ private final double x[] = {X, X};
+
+ @Override
+ public double getX(int i) { return x[i]; }
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSetByIndex_2.getClass(), "IGetSetByIndex-2");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+
+ // TODO: please uncomment/update after 8132973 fix
+ /*
+ IGetSetByIndex testGetSetByIndex_3 = new IGetSetByIndex() {
+
+ private double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX(int i) {
+ return x[i];
+ }
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ @Override
+ public void setX(int i, double v) {
+ x[i] = v;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSetByIndex_3.getClass(), "IGetSetByIndex-3");
+ System.out.println("OK = " + ok);
+ ok2 = checkAlternativeInfo(
+ testGetSetByIndex_3.getClass(), "IGetSetByIndex-3");
+ System.out.println("OK = " + ok2);
+ passed = passed && ok && ok2;
+ */
+
+ //----------------------------------------------------------------------
+
+ // TODO: please uncomment/update after 8155013 fix
+ /*
+ IGetSetBoth testGetSetBoth_1 = new IGetSetBoth() {
+
+ private double x[] = {X, X};
+
+ @Override
+ public double getX(int i) { return x[i]; }
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double[] getX() { return x; }
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+ @Override
+ public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSetBoth_1.getClass(), "IGetSetBoth-1");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+ */
+
+ // TODO: please uncomment/update after 8155013 fix
+ /*
+ IGetSetBoth testGetSetBoth_2 = new IGetSetBoth() {
+
+ private double x[] = {X, X};
+
+ @Override
+ public double getX(int i) { return x[i]; }
+ @Override
+ public double[] getX() { return x; }
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSetBoth_2.getClass(), "IGetSetBoth-2");
+ System.out.println("OK = " + ok);
+ passed = passed && ok;
+ */
+
+ // TODO: please uncomment/update after 8132973 fix
+ /*
+ IGetSetBoth testGetSetBoth_3 = new IGetSetBoth() {
+
+ private double x[] = {X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ @Override
+ public double getX(int i) { return x[i]; }
+ @Override
+ public double[] getX() { return x; }
+ @Override
+ public void setX(int i, double v) { x[i] = v; }
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ @Override
+ public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ };
+ ok = checkInfo(testGetSetBoth_3.getClass(), "IGetSetBoth-3");
+ System.out.println("OK = " + ok);
+ ok2 = checkAlternativeInfo(
+ testGetSetBoth_3.getClass(), "IGetSetBoth-3");
+ System.out.println("OK = " + ok2);
+ passed = passed && ok && ok2;
+ */
+
+ if (!passed) { throw new RuntimeException("test failed"); }
+ System.out.println("\ntest passed");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/BeanPropertyTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,1009 @@
+/*
+ * 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.beans.BeanInfo;
+import java.beans.BeanProperty;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyDescriptor;
+
+import java.util.Arrays;
+
+
+/**
+ * @test
+ * @bug 8132703 8132163 8132732 8132973 8154756 8132888
+ * @summary Some check for BeanProperty annotation
+ * @author a.stepanov
+ * @run main BeanPropertyTest
+ */
+
+
+public class BeanPropertyTest {
+
+ private final static String DESCRIPTION = "TEST";
+ private final static boolean BOUND = true;
+ private final static boolean EXPERT = false;
+ private final static boolean HIDDEN = true;
+ private final static boolean PREFERRED = false;
+ private final static boolean REQUIRED = true;
+ private final static boolean UPDATE = false;
+ private final static String
+ V_NAME = "javax.swing.SwingConstants.TOP",
+ V_SHORT = "TOP",
+ V = Integer.toString(javax.swing.SwingConstants.TOP);
+ private final static int X = javax.swing.SwingConstants.TOP;
+
+ private final static String DESCRIPTION_2 = "XYZ";
+
+
+ // ---------- test cases ----------
+
+ public static class G01 {
+
+ private final static String TESTCASE = "arbitrary getter name";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int get1() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class S01 {
+
+ private final static String TESTCASE = "arbitrary setter name";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setXXXXX(int v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132703
+ public static class G02 {
+
+ private final static String TESTCASE = "arbitrary getter name";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int get() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132703
+ public static class S02 {
+
+ private final static String TESTCASE = "arbitrary setter name";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void set(int v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132703
+ public static class G03 {
+
+ private final static String TESTCASE = "arbitrary getter name";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int GetX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132703
+ public static class S03 {
+
+ private final static String TESTCASE = "arbitrary setter name";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void SetX(int v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132163
+ public static class G04 {
+
+ private final static String TESTCASE = "arbitrary getter return type";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public Object getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132163
+ public static class S04 {
+
+ private final static String TESTCASE = "arbitrary setter argument type";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(short v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class G05 {
+
+ private final static String TESTCASE =
+ "annotated getter + arbitrary setter argument type";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getX() { return x; }
+ public void setX(short v) { x = v; }
+
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132163
+ public static class S05 {
+
+ private final static String TESTCASE =
+ "annotated setter + arbitrary getter return type";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int v) { x = v; }
+ public Object getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class G06 {
+
+ private final static String TESTCASE = "indexed getter";
+
+ private final int x[] = {X, X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getX(int i) { return x[i]; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class S06 {
+
+ private final static String TESTCASE = "indexed setter";
+
+ private final int x[] = {X, X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int i, int v) { x[i] = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class G07 {
+
+ private final static String TESTCASE =
+ "indexed (annotated) + non-indexed getters";
+
+ private final int x[] = {X, X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getX(int i) { return x[i]; }
+
+ public int[] getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class S07 {
+
+ private final static String TESTCASE =
+ "indexed (annotated) + non-indexed setters";
+
+ private int x[] = new int[3];
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int i, int v) { x[i] = v; }
+
+ public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132732
+ public static class G08 {
+
+ private final static String TESTCASE =
+ "non-indexed (annotated) + indexed getters";
+
+ private final int x[] = {X, X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int[] getX() { return x; }
+
+ public int getX(int i) { return x[i]; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132732
+ public static class S08 {
+
+ private final static String TESTCASE =
+ "non-indexed (annotated) + indexed setters";
+
+ private int x[] = new int[3];
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
+
+ public void setX(int i, int v) { x[i] = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132732
+ public static class G09 {
+
+ private final static String TESTCASE = "two annotated getters";
+
+ private final int x[] = {X, X, X};
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int[] getX() { return x; }
+
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ public int getX(int i) { return x[i]; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132732
+ public static class S09 {
+
+ private final static String TESTCASE = "two annotated setters";
+
+ private int x[] = new int[3];
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
+
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ public void setX(int i, int v) { x[i] = v; }
+
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class G10 {
+
+ private final static String TESTCASE =
+ "getter + similarly named field";
+
+ public int prop, Prop, setProp, getProp;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getProp() { return X; }
+ public void setProp(int v) { prop = Prop = setProp = getProp = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class S10 {
+
+ private final static String TESTCASE =
+ "setter + similarly named field";
+
+ public int prop, Prop, setProp, getProp;
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getProp() { return x; }
+ public void setProp(int v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class G11 {
+
+ private final static String TESTCASE =
+ "getter + similarly named field of other type";
+
+ public Object prop, Prop, setProp, getProp;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getProp() { return X; }
+ public void setProp(int v) { prop = Prop = setProp = getProp = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class S11 {
+
+ private final static String TESTCASE =
+ "setter + similarly named field of other type";
+
+ public String prop, Prop, setProp, getProp;
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getProp() { return x; }
+ public void setProp(int v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132163
+ public static class G12 {
+
+ private final static String TESTCASE =
+ "getter having wrapper class return type";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public Integer getProp() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132163
+ public static class S12 {
+
+ private final static String TESTCASE =
+ "setter with wrapper class argument type";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(Integer v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class G13 {
+
+ private final static String TESTCASE =
+ "getter + overloading methods";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getX() { return x; }
+ public int getX(boolean arg) { return (arg ? x : 0); }
+ public int getX(int ... dummy) { return 0; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8154756
+ public static class S13 {
+
+ private final static String TESTCASE =
+ "setter + overloading methods";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int v) { x = v; }
+ public int setX() { return (x = X); }
+ public void setX(int ... dummy) {}
+ private void setX(Object ... dummy) {}
+
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+
+ // JDK-8132888
+ public static class G14 {
+
+ private final static String TESTCASE = "non-public getter";
+
+ private final int x = X;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ int getX() { return x; } // getter is not public
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132888
+ public static class S14 {
+
+ private final static String TESTCASE = "non-public setter";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ void setX(int v) { x = v; } // setter is not public
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class getX {
+
+ private final static String TESTCASE =
+ "class name coincides with getter name";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getX() { return x; }
+ public void setX(int v) { x = v; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class setX {
+
+ private final static String TESTCASE =
+ "class name coincides with setter name";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public void setX(int v) { x = v; }
+ public int getX() { return x; }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ // JDK-8132973
+ public static class GS {
+
+ private final static String TESTCASE =
+ "both getter and setter are annotated";
+
+ private int x;
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE,
+ enumerationValues = {V_NAME})
+ public int getX() { return x; }
+
+ @BeanProperty(
+ description = DESCRIPTION_2,
+ bound = !BOUND,
+ expert = !EXPERT,
+ hidden = !HIDDEN,
+ preferred = !PREFERRED,
+ required = !REQUIRED,
+ visualUpdate = !UPDATE)
+ public void setX(int v) { x = v; }
+
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class Self {
+
+ private final static String TESTCASE = "trivial singleton";
+
+ private static Self instance = null;
+ private Self() {}
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE)
+ public Self getSelf() {
+ if (instance == null) { instance = new Self(); }
+ return instance;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+ public static class SelfArr {
+
+ private final static String TESTCASE = "trivial singleton + array";
+
+ private static SelfArr arr[] = null;
+ private SelfArr() {}
+
+ @BeanProperty(
+ description = DESCRIPTION,
+ bound = BOUND,
+ expert = EXPERT,
+ hidden = HIDDEN,
+ preferred = PREFERRED,
+ required = REQUIRED,
+ visualUpdate = UPDATE)
+ public SelfArr[] getSelfArr() {
+ if (arr == null) { arr = new SelfArr[]{new SelfArr(), new SelfArr()}; }
+ return arr;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {}
+ public void removePropertyChangeListener(PropertyChangeListener l) {}
+ }
+
+
+ // ---------- checks ----------
+
+ private static boolean check(String what, boolean v, boolean ref) {
+
+ boolean ok = (v == ref);
+ if (!ok) { System.out.println(
+ "invalid " + what + ": " + v + ", expected: " + ref); }
+ return ok;
+ }
+
+ private static boolean checkInfo(BeanInfo i, boolean checkVals) {
+
+ System.out.println("checking info...");
+
+ PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+ int nd = descriptors.length;
+ if (nd != 1) {
+ System.out.println("invalid number of descriptors: " + nd);
+ return false;
+ }
+
+ PropertyDescriptor d = descriptors[0];
+
+ String descr = d.getShortDescription();
+ boolean ok = descr.equals(DESCRIPTION);
+ if (!ok) { System.out.println("invalid description: " + descr +
+ ", expected: " + DESCRIPTION); }
+
+ ok &= check("isBound", d.isBound(), BOUND);
+ ok &= check("isExpert", d.isExpert(), EXPERT);
+ ok &= check("isHidden", d.isHidden(), HIDDEN);
+ ok &= check("isPreferred", d.isPreferred(), PREFERRED);
+ ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
+ ok &= check("visualUpdate",
+ (boolean) d.getValue("visualUpdate"), UPDATE);
+
+ if (!checkVals) { return ok; }
+
+ Object vals[] = (Object[]) d.getValue("enumerationValues");
+ if (vals == null) {
+ System.out.println("null enumerationValues");
+ return false;
+ }
+
+ boolean okVals = (
+ (vals.length == 3) &&
+ vals[0].toString().equals(V_SHORT) &&
+ vals[1].toString().equals(V) &&
+ vals[2].toString().equals(V_NAME));
+
+ if (!okVals) { System.out.println("invalid enumerationValues"); }
+
+ return (ok && okVals);
+ }
+
+ private static boolean checkAlternativeInfo(BeanInfo i) {
+
+ System.out.println("checking alternative info...");
+
+ PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+ int nd = descriptors.length;
+ if (nd != 1) {
+ System.out.println("invalid number of descriptors: " + nd);
+ return false;
+ }
+
+ PropertyDescriptor d = descriptors[0];
+
+ String descr = d.getShortDescription();
+ boolean ok = descr.equals(DESCRIPTION_2);
+ if (!ok) { System.out.println("invalid alternative description: " +
+ descr + ", expected: " + DESCRIPTION_2); }
+
+ ok &= check("isBound", d.isBound(), !BOUND);
+ ok &= check("isExpert", d.isExpert(), !EXPERT);
+ ok &= check("isHidden", d.isHidden(), !HIDDEN);
+ ok &= check("isPreferred", d.isPreferred(), !PREFERRED);
+ ok &= check("required", (boolean) d.getValue("required"), !REQUIRED);
+ ok &= check("visualUpdate",
+ (boolean) d.getValue("visualUpdate"), !UPDATE);
+
+ Object vals[] = (Object[]) d.getValue("enumerationValues");
+ if (vals != null || vals.length > 0) {
+ System.out.println("non-null enumerationValues");
+ return false;
+ }
+
+ return ok;
+ }
+
+
+ private static boolean checkAlternative(Class<?> c) {
+ return (
+ c.equals(G09.class) ||
+ c.equals(S09.class) ||
+ c.equals(GS.class));
+ }
+
+ private static boolean ignoreVals(Class<?> c) {
+ return (c.equals(Self.class) || c.equals(SelfArr.class));
+ }
+
+
+ // ---------- run test ----------
+
+ public static void main(String[] args) throws Exception {
+
+ Class<?> cases[] = {
+
+ G01.class, S01.class,
+ // G02.class, S02.class, // TODO: please update after 8132703 fix
+ // G03.class, S03.class, // TODO: please update after 8132703 fix
+ // G04.class, S04.class, // TODO: please update after 8132163 fix
+ G05.class, // S05.class, // TODO: please update after 8132163 fix
+ G06.class, S06.class,
+ G07.class, S07.class,
+ // G08.class, S08.class, // TODO: please update after 8132732 fix
+ // G09.class, S09.class, // TODO: please update after 8132732 fix
+ G10.class, S10.class,
+ G11.class, S11.class,
+ // G12.class, S12.class, // TODO: please update after 8132163 fix
+ G13.class, // S13.class, // TODO: please update after 8154756 fix
+ // G14.class, S14.class, // TODO: please update after 8132888 fix or
+ // remove these cases if it is not an issue
+ // GS.class, // TODO: please update after 8132973 fix
+ getX.class, setX.class,
+ Self.class, SelfArr.class
+ };
+
+ boolean passed = true;
+
+ for (Class<?> c: cases) {
+
+ java.lang.reflect.Field f = c.getDeclaredField("TESTCASE");
+ f.setAccessible(true);
+ String descr = f.get(c).toString();
+
+ System.out.println("\n" + c.getSimpleName() + " (" + descr + "):");
+ BeanInfo i;
+ try { i = Introspector.getBeanInfo(c, Object.class); }
+ catch (IntrospectionException e) { throw new RuntimeException(e); }
+ boolean ok = checkInfo(i, !ignoreVals(c));
+ if (checkAlternative(c)) {
+ ok |= checkAlternativeInfo(i);
+ }
+ System.out.println(ok ? "OK" : "NOK");
+ passed = passed && ok;
+ }
+
+ if (!passed) { throw new RuntimeException("test failed"); }
+ System.out.println("\ntest passed");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/concat/WithSecurityManager.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 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.security.Permission;
+
+/**
+ * @test
+ * @summary String concatenation fails with a custom SecurityManager that uses concatenation
+ * @bug 8155090
+ *
+ * @compile WithSecurityManager.java
+ *
+ * @run main/othervm -Xverify:all WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager
+*/
+public class WithSecurityManager {
+ public static void main(String[] args) throws Throwable {
+ SecurityManager sm = new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ String abc = "abc";
+ String full = abc + "def";
+ }
+ };
+ System.setSecurityManager(sm);
+ ClassLoader cl = new ClassLoader() {};
+ }
+}
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java Fri May 06 06:23:30 2016 -0700
@@ -148,6 +148,7 @@
COMPARE_AND_EXCHANGE_ACQUIRE(TestAccessType.COMPARE_AND_EXCHANGE),
COMPARE_AND_EXCHANGE_RELEASE(TestAccessType.COMPARE_AND_EXCHANGE),
WEAK_COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
+ WEAK_COMPARE_AND_SET_VOLATILE(TestAccessType.COMPARE_AND_SET),
WEAK_COMPARE_AND_SET_ACQUIRE(TestAccessType.COMPARE_AND_SET),
WEAK_COMPARE_AND_SET_RELEASE(TestAccessType.COMPARE_AND_SET),
GET_AND_SET(TestAccessType.GET_AND_SET),
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -280,6 +281,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, true, false);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
});
@@ -362,6 +367,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(true, false);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(true, false);
});
@@ -434,6 +443,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, true, false);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
});
@@ -506,6 +519,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(true, false);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(true, false);
});
@@ -585,6 +602,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, true, false);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, true, false);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -280,6 +281,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
});
@@ -362,6 +367,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
});
@@ -434,6 +443,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
});
@@ -506,6 +519,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
});
@@ -585,6 +602,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, (byte)1, (byte)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -280,6 +281,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b');
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
});
@@ -362,6 +367,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile('a', 'b');
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire('a', 'b');
});
@@ -434,6 +443,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b');
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
});
@@ -506,6 +519,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile('a', 'b');
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire('a', 'b');
});
@@ -585,6 +602,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, 'a', 'b');
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b');
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -280,6 +281,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
});
@@ -362,6 +367,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
});
@@ -434,6 +443,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
});
@@ -506,6 +519,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
});
@@ -585,6 +602,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, 1.0d, 2.0d);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0d, 2.0d);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -280,6 +281,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1.0f, 2.0f);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
});
@@ -362,6 +367,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(1.0f, 2.0f);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
});
@@ -434,6 +443,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1.0f, 2.0f);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
});
@@ -506,6 +519,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(1.0f, 2.0f);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
});
@@ -585,6 +602,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, 1.0f, 2.0f);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0f, 2.0f);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -421,12 +422,19 @@
assertEquals(x, 2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 2, 1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) vh.get(recv);
+ assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) vh.getAndSet(recv, 1);
- assertEquals(o, 2, "getAndSet int");
+ int o = (int) vh.getAndSet(recv, 2);
+ assertEquals(o, 1, "getAndSet int");
int x = (int) vh.get(recv);
- assertEquals(x, 1, "getAndSet int value");
+ assertEquals(x, 2, "getAndSet int value");
}
vh.set(recv, 1);
@@ -549,18 +557,25 @@
}
{
- boolean r = (boolean) vh.weakCompareAndSetRelease( 1, 2);
+ boolean r = (boolean) vh.weakCompareAndSetRelease(1, 2);
assertEquals(r, true, "weakCompareAndSetRelease int");
int x = (int) vh.get();
assertEquals(x, 2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = (boolean) vh.weakCompareAndSetVolatile(2, 1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) vh.get();
+ assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) vh.getAndSet( 1);
- assertEquals(o, 2, "getAndSet int");
+ int o = (int) vh.getAndSet( 2);
+ assertEquals(o, 1, "getAndSet int");
int x = (int) vh.get();
- assertEquals(x, 1, "getAndSet int value");
+ assertEquals(x, 2, "getAndSet int value");
}
vh.set(1);
@@ -692,12 +707,19 @@
assertEquals(x, 2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, 2, 1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) vh.get(array, i);
+ assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) vh.getAndSet(array, i, 1);
- assertEquals(o, 2, "getAndSet int");
+ int o = (int) vh.getAndSet(array, i, 2);
+ assertEquals(o, 1, "getAndSet int");
int x = (int) vh.get(array, i);
- assertEquals(x, 1, "getAndSet int value");
+ assertEquals(x, 2, "getAndSet int value");
}
vh.set(array, i, 1);
@@ -778,6 +800,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, 1, 2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, 1, 2);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -421,12 +422,19 @@
assertEquals(x, 2L, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(recv, 2L, 1L);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) vh.get(recv);
+ assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) vh.getAndSet(recv, 1L);
- assertEquals(o, 2L, "getAndSet long");
+ long o = (long) vh.getAndSet(recv, 2L);
+ assertEquals(o, 1L, "getAndSet long");
long x = (long) vh.get(recv);
- assertEquals(x, 1L, "getAndSet long value");
+ assertEquals(x, 2L, "getAndSet long value");
}
vh.set(recv, 1L);
@@ -549,18 +557,25 @@
}
{
- boolean r = (boolean) vh.weakCompareAndSetRelease( 1L, 2L);
+ boolean r = (boolean) vh.weakCompareAndSetRelease(1L, 2L);
assertEquals(r, true, "weakCompareAndSetRelease long");
long x = (long) vh.get();
assertEquals(x, 2L, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = (boolean) vh.weakCompareAndSetVolatile(2L, 1L);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) vh.get();
+ assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) vh.getAndSet( 1L);
- assertEquals(o, 2L, "getAndSet long");
+ long o = (long) vh.getAndSet( 2L);
+ assertEquals(o, 1L, "getAndSet long");
long x = (long) vh.get();
- assertEquals(x, 1L, "getAndSet long value");
+ assertEquals(x, 2L, "getAndSet long value");
}
vh.set(1L);
@@ -692,12 +707,19 @@
assertEquals(x, 2L, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, 2L, 1L);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) vh.get(array, i);
+ assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) vh.getAndSet(array, i, 1L);
- assertEquals(o, 2L, "getAndSet long");
+ long o = (long) vh.getAndSet(array, i, 2L);
+ assertEquals(o, 1L, "getAndSet long");
long x = (long) vh.get(array, i);
- assertEquals(x, 1L, "getAndSet long value");
+ assertEquals(x, 2L, "getAndSet long value");
}
vh.set(array, i, 1L);
@@ -778,6 +800,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, 1L, 2L);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, 1L, 2L);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -280,6 +281,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, (short)1, (short)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
});
@@ -362,6 +367,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile((short)1, (short)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
});
@@ -434,6 +443,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, (short)1, (short)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
});
@@ -506,6 +519,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile((short)1, (short)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
});
@@ -585,6 +602,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, (short)1, (short)2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, (short)1, (short)2);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java Fri May 06 06:23:30 2016 -0700
@@ -104,6 +104,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -435,12 +436,19 @@
assertEquals(x, "bar", "weakCompareAndSetRelease String");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(recv, "bar", "foo");
+ assertEquals(r, true, "weakCompareAndSetVolatile String");
+ String x = (String) vh.get(recv);
+ assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+ }
+
// Compare set and get
{
- String o = (String) vh.getAndSet(recv, "foo");
- assertEquals(o, "bar", "getAndSet String");
+ String o = (String) vh.getAndSet(recv, "bar");
+ assertEquals(o, "foo", "getAndSet String");
String x = (String) vh.get(recv);
- assertEquals(x, "foo", "getAndSet String value");
+ assertEquals(x, "bar", "getAndSet String value");
}
}
@@ -561,18 +569,25 @@
}
{
- boolean r = (boolean) vh.weakCompareAndSetRelease( "foo", "bar");
+ boolean r = (boolean) vh.weakCompareAndSetRelease("foo", "bar");
assertEquals(r, true, "weakCompareAndSetRelease String");
String x = (String) vh.get();
assertEquals(x, "bar", "weakCompareAndSetRelease String");
}
+ {
+ boolean r = (boolean) vh.weakCompareAndSetVolatile("bar", "foo");
+ assertEquals(r, true, "weakCompareAndSetVolatile String");
+ String x = (String) vh.get();
+ assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+ }
+
// Compare set and get
{
- String o = (String) vh.getAndSet( "foo");
- assertEquals(o, "bar", "getAndSet String");
+ String o = (String) vh.getAndSet( "bar");
+ assertEquals(o, "foo", "getAndSet String");
String x = (String) vh.get();
- assertEquals(x, "foo", "getAndSet String value");
+ assertEquals(x, "bar", "getAndSet String value");
}
}
@@ -702,12 +717,19 @@
assertEquals(x, "bar", "weakCompareAndSetRelease String");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, "bar", "foo");
+ assertEquals(r, true, "weakCompareAndSetVolatile String");
+ String x = (String) vh.get(array, i);
+ assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+ }
+
// Compare set and get
{
- String o = (String) vh.getAndSet(array, i, "foo");
- assertEquals(o, "bar", "getAndSet String");
+ String o = (String) vh.getAndSet(array, i, "bar");
+ assertEquals(o, "foo", "getAndSet String");
String x = (String) vh.get(array, i);
- assertEquals(x, "foo", "getAndSet String value");
+ assertEquals(x, "bar", "getAndSet String value");
}
}
@@ -786,6 +808,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, "foo", "bar");
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, "foo", "bar");
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java Fri May 06 06:23:30 2016 -0700
@@ -93,6 +93,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -204,6 +205,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -265,6 +270,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -306,6 +315,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java Fri May 06 06:23:30 2016 -0700
@@ -93,6 +93,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -239,6 +240,10 @@
});
checkROBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkROBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -334,6 +339,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -415,6 +424,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -487,6 +500,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -562,6 +579,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -699,12 +720,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile double");
+ double x = (double) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile double value");
+ }
+
// Compare set and get
{
- double o = (double) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet double");
+ double o = (double) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet double");
double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet double value");
+ assertEquals(x, VALUE_2, "getAndSet double value");
}
}
@@ -832,12 +860,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile double");
+ double x = (double) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile double value");
+ }
+
// Compare set and get
{
- double o = (double) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet double");
+ double o = (double) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet double");
double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet double value");
+ assertEquals(x, VALUE_2, "getAndSet double value");
}
}
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java Fri May 06 06:23:30 2016 -0700
@@ -93,6 +93,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -239,6 +240,10 @@
});
checkROBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkROBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -334,6 +339,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -415,6 +424,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -487,6 +500,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -562,6 +579,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -699,12 +720,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile float");
+ float x = (float) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile float value");
+ }
+
// Compare set and get
{
- float o = (float) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet float");
+ float o = (float) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet float");
float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet float value");
+ assertEquals(x, VALUE_2, "getAndSet float value");
}
}
@@ -832,12 +860,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile float");
+ float x = (float) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile float value");
+ }
+
// Compare set and get
{
- float o = (float) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet float");
+ float o = (float) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet float");
float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet float value");
+ assertEquals(x, VALUE_2, "getAndSet float value");
}
}
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java Fri May 06 06:23:30 2016 -0700
@@ -38,10 +38,10 @@
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.EnumSet;
import java.util.List;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.*;
public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
static final int SIZE = Integer.BYTES;
@@ -93,6 +93,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -232,6 +233,10 @@
});
checkROBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkROBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -320,6 +325,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -408,6 +417,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -487,6 +500,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -569,6 +586,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -713,12 +734,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet int");
+ int o = (int) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet int");
int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet int value");
+ assertEquals(x, VALUE_2, "getAndSet int value");
}
vh.set(array, i, VALUE_1);
@@ -855,12 +883,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet int");
+ int o = (int) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet int");
int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet int value");
+ assertEquals(x, VALUE_2, "getAndSet int value");
}
vh.set(array, i, VALUE_1);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java Fri May 06 06:23:30 2016 -0700
@@ -93,6 +93,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -232,6 +233,10 @@
});
checkROBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkROBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -320,6 +325,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -408,6 +417,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -487,6 +500,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -569,6 +586,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -713,12 +734,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet long");
+ long o = (long) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet long");
long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet long value");
+ assertEquals(x, VALUE_2, "getAndSet long value");
}
vh.set(array, i, VALUE_1);
@@ -855,12 +883,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet long");
+ long o = (long) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet long");
long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet long value");
+ assertEquals(x, VALUE_2, "getAndSet long value");
}
vh.set(array, i, VALUE_1);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java Fri May 06 06:23:30 2016 -0700
@@ -93,6 +93,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -204,6 +205,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -265,6 +270,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -306,6 +315,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java Fri May 06 06:23:30 2016 -0700
@@ -228,12 +228,19 @@
assertEquals(x, 2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+ assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 1);
- assertEquals(o, 2, "getAndSet int");
+ int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2);
+ assertEquals(o, 1, "getAndSet int");
int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
- assertEquals(x, 1, "getAndSet int value");
+ assertEquals(x, 2, "getAndSet int value");
}
hs.get(TestAccessMode.SET).invokeExact(recv, 1);
@@ -356,18 +363,25 @@
}
{
- boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1, 2);
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2);
assertEquals(r, true, "weakCompareAndSetRelease int");
int x = (int) hs.get(TestAccessMode.GET).invokeExact();
assertEquals(x, 2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+ assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 1);
- assertEquals(o, 2, "getAndSet int");
+ int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2);
+ assertEquals(o, 1, "getAndSet int");
int x = (int) hs.get(TestAccessMode.GET).invokeExact();
- assertEquals(x, 1, "getAndSet int value");
+ assertEquals(x, 2, "getAndSet int value");
}
hs.get(TestAccessMode.SET).invokeExact(1);
@@ -499,12 +513,19 @@
assertEquals(x, 2, "weakCompareAndSetRelease int");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1);
+ assertEquals(r, true, "weakCompareAndSetVolatile int");
+ int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+ assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+ }
+
// Compare set and get
{
- int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 1);
- assertEquals(o, 2, "getAndSet int");
+ int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2);
+ assertEquals(o, 1, "getAndSet int");
int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
- assertEquals(x, 1, "getAndSet int value");
+ assertEquals(x, 2, "getAndSet int value");
}
hs.get(TestAccessMode.SET).invokeExact(array, i, 1);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java Fri May 06 06:23:30 2016 -0700
@@ -228,12 +228,19 @@
assertEquals(x, 2L, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+ assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 1L);
- assertEquals(o, 2L, "getAndSet long");
+ long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2L);
+ assertEquals(o, 1L, "getAndSet long");
long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
- assertEquals(x, 1L, "getAndSet long value");
+ assertEquals(x, 2L, "getAndSet long value");
}
hs.get(TestAccessMode.SET).invokeExact(recv, 1L);
@@ -356,18 +363,25 @@
}
{
- boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1L, 2L);
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L);
assertEquals(r, true, "weakCompareAndSetRelease long");
long x = (long) hs.get(TestAccessMode.GET).invokeExact();
assertEquals(x, 2L, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+ assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 1L);
- assertEquals(o, 2L, "getAndSet long");
+ long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2L);
+ assertEquals(o, 1L, "getAndSet long");
long x = (long) hs.get(TestAccessMode.GET).invokeExact();
- assertEquals(x, 1L, "getAndSet long value");
+ assertEquals(x, 2L, "getAndSet long value");
}
hs.get(TestAccessMode.SET).invokeExact(1L);
@@ -499,12 +513,19 @@
assertEquals(x, 2L, "weakCompareAndSetRelease long");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L);
+ assertEquals(r, true, "weakCompareAndSetVolatile long");
+ long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+ assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+ }
+
// Compare set and get
{
- long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 1L);
- assertEquals(o, 2L, "getAndSet long");
+ long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2L);
+ assertEquals(o, 1L, "getAndSet long");
long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
- assertEquals(x, 1L, "getAndSet long value");
+ assertEquals(x, 2L, "getAndSet long value");
}
hs.get(TestAccessMode.SET).invokeExact(array, i, 1L);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java Fri May 06 06:23:30 2016 -0700
@@ -228,12 +228,19 @@
assertEquals(x, "bar", "weakCompareAndSetRelease String");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo");
+ assertEquals(r, true, "weakCompareAndSetVolatile String");
+ String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+ assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+ }
+
// Compare set and get
{
- String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "foo");
- assertEquals(o, "bar", "getAndSet String");
+ String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar");
+ assertEquals(o, "foo", "getAndSet String");
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
- assertEquals(x, "foo", "getAndSet String value");
+ assertEquals(x, "bar", "getAndSet String value");
}
}
@@ -352,18 +359,25 @@
}
{
- boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( "foo", "bar");
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar");
assertEquals(r, true, "weakCompareAndSetRelease String");
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
assertEquals(x, "bar", "weakCompareAndSetRelease String");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo");
+ assertEquals(r, true, "weakCompareAndSetVolatile String");
+ String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+ assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+ }
+
// Compare set and get
{
- String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact( "foo");
- assertEquals(o, "bar", "getAndSet String");
+ String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar");
+ assertEquals(o, "foo", "getAndSet String");
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
- assertEquals(x, "foo", "getAndSet String value");
+ assertEquals(x, "bar", "getAndSet String value");
}
}
@@ -491,12 +505,19 @@
assertEquals(x, "bar", "weakCompareAndSetRelease String");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo");
+ assertEquals(r, true, "weakCompareAndSetVolatile String");
+ String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+ assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+ }
+
// Compare set and get
{
- String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "foo");
- assertEquals(o, "bar", "getAndSet String");
+ String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "bar");
+ assertEquals(o, "foo", "getAndSet String");
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
- assertEquals(x, "foo", "getAndSet String value");
+ assertEquals(x, "bar", "getAndSet String value");
}
}
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java Fri May 06 06:23:30 2016 -0700
@@ -374,6 +374,32 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, 1, 1);
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 1, 1);
+ });
+ checkWMTE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, 1);
+ });
+ checkWMTE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1, Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, 1, 1);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1, 1, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
@@ -972,6 +998,23 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkWMTE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 1);
+ });
+ checkWMTE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(1, Void.class);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(1, 1, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkWMTE(() -> { // expected reference class
@@ -1566,6 +1609,35 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, 0, 1, 1);
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, 1, 1);
+ });
+ checkWMTE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, 1);
+ });
+ checkWMTE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, 1, Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, 0, 1, 1);
+ });
+ checkWMTE(() -> { // index reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, Void.class, 1, 1);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, 1, 1, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java Fri May 06 06:23:30 2016 -0700
@@ -374,6 +374,32 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, 1L, 1L);
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 1L, 1L);
+ });
+ checkWMTE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, 1L);
+ });
+ checkWMTE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1L, Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, 1L, 1L);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(recv, 1L, 1L, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
@@ -972,6 +998,23 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkWMTE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 1L);
+ });
+ checkWMTE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(1L, Void.class);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(1L, 1L, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkWMTE(() -> { // expected reference class
@@ -1566,6 +1609,35 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, 0, 1L, 1L);
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, 1L, 1L);
+ });
+ checkWMTE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, 1L);
+ });
+ checkWMTE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, 1L, Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, 0, 1L, 1L);
+ });
+ checkWMTE(() -> { // index reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, Void.class, 1L, 1L);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, 1L, 1L, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java Fri May 06 06:23:30 2016 -0700
@@ -374,6 +374,32 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, "foo", "foo");
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, "foo", "foo");
+ });
+ checkCCE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, "foo");
+ });
+ checkCCE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, "foo", Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, "foo", "foo");
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(recv, "foo", "foo", Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
@@ -878,6 +904,23 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkCCE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, "foo");
+ });
+ checkCCE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile("foo", Void.class);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile("foo", "foo", Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkCCE(() -> { // expected reference class
@@ -1407,6 +1450,35 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, 0, "foo", "foo");
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, "foo", "foo");
+ });
+ checkCCE(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, "foo");
+ });
+ checkCCE(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, "foo", Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, 0, "foo", "foo");
+ });
+ checkWMTE(() -> { // index reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, Void.class, "foo", "foo");
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, "foo", "foo", Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template Fri May 06 06:23:30 2016 -0700
@@ -105,6 +105,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -114,6 +115,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -297,6 +299,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value2$);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
});
@@ -383,6 +389,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile($value1$, $value2$);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
});
@@ -514,12 +524,19 @@
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) vh.get(recv);
+ assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) vh.getAndSet(recv, $value1$);
- assertEquals(o, $value2$, "getAndSet $type$");
+ $type$ o = ($type$) vh.getAndSet(recv, $value2$);
+ assertEquals(o, $value1$, "getAndSet $type$");
$type$ x = ($type$) vh.get(recv);
- assertEquals(x, $value1$, "getAndSet $type$ value");
+ assertEquals(x, $value2$, "getAndSet $type$ value");
}
#end[CAS]
@@ -559,6 +576,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value2$);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
});
@@ -684,18 +705,25 @@
}
{
- boolean r = (boolean) vh.weakCompareAndSetRelease( $value1$, $value2$);
+ boolean r = (boolean) vh.weakCompareAndSetRelease($value1$, $value2$);
assertEquals(r, true, "weakCompareAndSetRelease $type$");
$type$ x = ($type$) vh.get();
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = (boolean) vh.weakCompareAndSetVolatile($value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) vh.get();
+ assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) vh.getAndSet( $value1$);
- assertEquals(o, $value2$, "getAndSet $type$");
+ $type$ o = ($type$) vh.getAndSet( $value2$);
+ assertEquals(o, $value1$, "getAndSet $type$");
$type$ x = ($type$) vh.get();
- assertEquals(x, $value1$, "getAndSet $type$ value");
+ assertEquals(x, $value2$, "getAndSet $type$ value");
}
#end[CAS]
@@ -735,6 +763,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile($value1$, $value2$);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
});
@@ -869,12 +901,19 @@
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) vh.get(array, i);
+ assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) vh.getAndSet(array, i, $value1$);
- assertEquals(o, $value2$, "getAndSet $type$");
+ $type$ o = ($type$) vh.getAndSet(array, i, $value2$);
+ assertEquals(o, $value1$, "getAndSet $type$");
$type$ x = ($type$) vh.get(array, i);
- assertEquals(x, $value1$, "getAndSet $type$ value");
+ assertEquals(x, $value2$, "getAndSet $type$ value");
}
#end[CAS]
@@ -918,6 +957,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, $value1$, $value2$);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, i, $value1$, $value2$);
});
@@ -997,6 +1040,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, $value1$, $value2$);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, $value1$, $value2$);
});
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template Fri May 06 06:23:30 2016 -0700
@@ -94,6 +94,7 @@
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -103,6 +104,7 @@
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -221,6 +223,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -291,6 +297,10 @@
});
checkROBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkROBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -322,6 +332,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -375,6 +389,10 @@
});
checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -461,6 +479,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -553,6 +575,10 @@
});
checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkIOOBE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -636,6 +662,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -722,6 +752,10 @@
});
checkISE(() -> {
+ boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
@@ -870,12 +904,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet $type$");
+ $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet $type$");
$type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet $type$ value");
+ assertEquals(x, VALUE_2, "getAndSet $type$ value");
}
#end[CAS]
@@ -1016,12 +1057,19 @@
assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) vh.get(array, i);
+ assertEquals(x, VALUE_1, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
- assertEquals(o, VALUE_2, "getAndSet $type$");
+ $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
+ assertEquals(o, VALUE_1, "getAndSet $type$");
$type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "getAndSet $type$ value");
+ assertEquals(x, VALUE_2, "getAndSet $type$ value");
}
#end[CAS]
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template Fri May 06 06:23:30 2016 -0700
@@ -229,12 +229,19 @@
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+ assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value1$);
- assertEquals(o, $value2$, "getAndSet $type$");
+ $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value2$);
+ assertEquals(o, $value1$, "getAndSet $type$");
$type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
- assertEquals(x, $value1$, "getAndSet $type$ value");
+ assertEquals(x, $value2$, "getAndSet $type$ value");
}
#end[CAS]
@@ -387,18 +394,25 @@
}
{
- boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( $value1$, $value2$);
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$);
assertEquals(r, true, "weakCompareAndSetRelease $type$");
$type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+ assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact( $value1$);
- assertEquals(o, $value2$, "getAndSet $type$");
+ $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact($value2$);
+ assertEquals(o, $value1$, "getAndSet $type$");
$type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
- assertEquals(x, $value1$, "getAndSet $type$ value");
+ assertEquals(x, $value2$, "getAndSet $type$ value");
}
#end[CAS]
@@ -560,12 +574,19 @@
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
}
+ {
+ boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+ $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+ assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+ }
+
// Compare set and get
{
- $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value1$);
- assertEquals(o, $value2$, "getAndSet $type$");
+ $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value2$);
+ assertEquals(o, $value1$, "getAndSet $type$");
$type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
- assertEquals(x, $value1$, "getAndSet $type$ value");
+ assertEquals(x, $value2$, "getAndSet $type$ value");
}
#end[CAS]
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template Fri May 06 06:23:30 2016 -0700
@@ -375,6 +375,32 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, $value1$, $value1$);
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, $value1$, $value1$);
+ });
+ check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, $value1$);
+ });
+ check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, $value1$, $value1$);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value1$, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
@@ -981,6 +1007,23 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, $value1$);
+ });
+ check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile($value1$, Void.class);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile($value1$, $value1$, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
check{#if[String]?CCE:WMTE}(() -> { // expected reference class
@@ -1583,6 +1626,35 @@
});
+ // WeakCompareAndSetVolatile
+ // Incorrect argument types
+ checkNPE(() -> { // null receiver
+ boolean r = vh.weakCompareAndSetVolatile(null, 0, $value1$, $value1$);
+ });
+ checkCCE(() -> { // receiver reference class
+ boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, $value1$, $value1$);
+ });
+ check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, $value1$);
+ });
+ check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, $value1$, Void.class);
+ });
+ checkWMTE(() -> { // receiver primitive class
+ boolean r = vh.weakCompareAndSetVolatile(0, 0, $value1$, $value1$);
+ });
+ checkWMTE(() -> { // index reference class
+ boolean r = vh.weakCompareAndSetVolatile(array, Void.class, $value1$, $value1$);
+ });
+ // Incorrect arity
+ checkWMTE(() -> { // 0
+ boolean r = vh.weakCompareAndSetVolatile();
+ });
+ checkWMTE(() -> { // >
+ boolean r = vh.weakCompareAndSetVolatile(array, 0, $value1$, $value1$, Void.class);
+ });
+
+
// WeakCompareAndSetAcquire
// Incorrect argument types
checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarargsArrayTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/invoke/VarargsArrayTest.java Fri May 06 06:23:30 2016 -0700
@@ -37,7 +37,7 @@
* @library /lib/testlibrary /lib/testlibrary/jsr292
* @compile/module=java.base java/lang/invoke/MethodHandleHelper.java
* @run main/bootclasspath VarargsArrayTest
- * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
+ * @run main/bootclasspath/othervm -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
* VarargsArrayTest
*/
--- a/jdk/test/java/lang/module/ModuleFinderTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/lang/module/ModuleFinderTest.java Fri May 06 06:23:30 2016 -0700
@@ -340,7 +340,7 @@
*/
public void testOfWithUnrecognizedEntry() throws Exception {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
- Path mod = Files.createTempFile(dir, "m", "mod");
+ Path mod = Files.createTempFile(dir, "m", ".junk");
ModuleFinder finder = ModuleFinder.of(mod);
try {
@@ -361,6 +361,48 @@
/**
+ * Test ModuleFinder.of with a file path to a directory containing a file
+ * that will not be recognized as a module.
+ */
+ public void testOfWithUnrecognizedEntryInDirectory() throws Exception {
+ Path dir = Files.createTempDirectory(USER_DIR, "mods");
+ Files.createTempFile(dir, "m", ".junk");
+
+ ModuleFinder finder = ModuleFinder.of(dir);
+ try {
+ finder.find("java.rhubarb");
+ assertTrue(false);
+ } catch (FindException e) {
+ // expected
+ }
+
+ finder = ModuleFinder.of(dir);
+ try {
+ finder.findAll();
+ assertTrue(false);
+ } catch (FindException e) {
+ // expected
+ }
+ }
+
+
+ /**
+ * Test ModuleFinder.of with a file path to a directory containing a file
+ * starting with ".", the file should be ignored.
+ */
+ public void testOfWithHiddenEntryInDirectory() throws Exception {
+ Path dir = Files.createTempDirectory(USER_DIR, "mods");
+ Files.createTempFile(dir, ".marker", "");
+
+ ModuleFinder finder = ModuleFinder.of(dir);
+ assertFalse(finder.find("java.rhubarb").isPresent());
+
+ finder = ModuleFinder.of(dir);
+ assertTrue(finder.findAll().isEmpty());
+ }
+
+
+ /**
* Test ModuleFinder.of with a directory that contains two
* versions of the same module
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/WeakPairMap/Driver.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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 8888888
+ * @summary Functional test for WeakPairMap
+ * @build java.base/java.lang.reflect.WeakPairMapTest
+ * @run main Driver
+ */
+public class Driver {
+ public static void main(String[] args) {
+ java.lang.reflect.WeakPairMapTest.main(args);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/WeakPairMap/java.base/java/lang/reflect/WeakPairMapTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,175 @@
+/*
+ * 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 java.lang.reflect;
+
+import java.lang.ref.Reference;
+import java.util.Objects;
+
+/**
+ * Functional test for WeakPairMap
+ *
+ * @author Peter Levart
+ */
+public class WeakPairMapTest {
+ public static void main(String[] args) {
+ WeakPairMap<Object, Object, String> pm = new WeakPairMap<>();
+ Object key1 = new Object();
+ Object key2 = new Object();
+
+ // check for emptiness
+ assertEquals(pm.containsKeyPair(key1, key2), false);
+ assertEquals(pm.get(key1, key2), null);
+
+ // check for NPE(s)
+ for (Object k1 : new Object[]{null, key1}) {
+ for (Object k2 : new Object[]{null, key2}) {
+ for (String v : new String[]{null, "abc"}) {
+
+ if (k1 != null && k2 != null && v != null) {
+ // skip non-null args
+ continue;
+ }
+
+ try {
+ pm.put(k1, k2, v);
+ throw new AssertionError("Unexpected code path, k1=" +
+ k1 + ", k2=" + k2 + ", v=" + v);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ pm.putIfAbsent(k1, k2, v);
+ throw new AssertionError("Unexpected code path, k1=" +
+ k1 + ", k2=" + k2 + ", v=" + v);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ if (k1 != null && k2 != null) {
+ // skip non-null args
+ continue;
+ }
+
+ try {
+ pm.computeIfAbsent(k1, k2, (_k1, _k2) -> v);
+ throw new AssertionError("Unexpected code path, k1=" +
+ k1 + ", k2=" + k2 + ", v=" + v);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ pm.containsKeyPair(k1, k2);
+ throw new AssertionError("Unexpected code path, k1=" +
+ k1 + ", k2=" + k2);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ pm.get(k1, k2);
+ throw new AssertionError("Unexpected code path, k1=" +
+ k1 + ", k2=" + k2);
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ // how much to wait when it is expected for entry to be retained
+ final long retentionTimeout = 500L;
+ // how much to wait when it is expected for entry to be removed
+ final long cleanupTimeout = 30_000L;
+
+ // check insertion
+ assertEquals(pm.putIfAbsent(key1, key2, "abc"), null);
+ assertEquals(pm.get(key1, key2), "abc");
+
+ // check retention while both keys are still reachable
+ assertEquals(gcAndWaitRemoved(pm, "abc", retentionTimeout), false);
+ assertEquals(pm.get(key1, key2), "abc");
+
+ // check cleanup when both keys are unreachable
+ key1 = null;
+ key2 = null;
+ assertEquals(gcAndWaitRemoved(pm, "abc", cleanupTimeout), true);
+
+ // new insertion
+ key1 = new Object();
+ key2 = new Object();
+ assertEquals(pm.putIfAbsent(key1, key2, "abc"), null);
+ assertEquals(pm.get(key1, key2), "abc");
+
+ // check retention while both keys are still reachable
+ assertEquals(gcAndWaitRemoved(pm, "abc", retentionTimeout), false);
+ assertEquals(pm.get(key1, key2), "abc");
+
+ // check cleanup when 1st key is unreachable
+ key1 = null;
+ assertEquals(gcAndWaitRemoved(pm, "abc", cleanupTimeout), true);
+ Reference.reachabilityFence(key2);
+
+ // new insertion
+ key1 = new Object();
+ key2 = new Object();
+ assertEquals(pm.putIfAbsent(key1, key2, "abc"), null);
+ assertEquals(pm.get(key1, key2), "abc");
+
+ // check retention while both keys are still reachable
+ assertEquals(gcAndWaitRemoved(pm, "abc", retentionTimeout), false);
+ assertEquals(pm.get(key1, key2), "abc");
+
+ // check cleanup when 2nd key is unreachable
+ key2 = null;
+ assertEquals(gcAndWaitRemoved(pm, "abc", cleanupTimeout), true);
+ Reference.reachabilityFence(key1);
+ }
+
+ /**
+ * Trigger GC and wait for at most {@code millis} ms for given value to
+ * be removed from given WeakPairMap.
+ *
+ * @return true if element has been removed or false if not
+ */
+ static <V> boolean gcAndWaitRemoved(WeakPairMap<?, ?, V> pm, V value,
+ long millis) {
+ System.gc();
+ for (int i = 0; i < (millis + 99) / 100 && pm.values().contains(value); i++) {
+ try {
+ Thread.sleep(100L);
+ } catch (InterruptedException e) {
+ throw new AssertionError("Interrupted");
+ }
+ }
+ return !pm.values().contains(value);
+ }
+
+ static void assertEquals(Object actual, Object expected) {
+ if (!Objects.equals(actual, expected)) {
+ throw new AssertionError("Expected: " + expected + ", actual: " + actual);
+ }
+ }
+}
--- a/jdk/test/java/net/httpclient/APIErrors.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/APIErrors.java Fri May 06 06:23:30 2016 -0700
@@ -26,6 +26,7 @@
* @bug 8087112
* @library /lib/testlibrary/
* @build jdk.testlibrary.SimpleSSLContext ProxyServer
+ * @build TestKit
* @compile ../../../com/sun/net/httpserver/LogFilter.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @run main/othervm APIErrors
@@ -73,26 +74,6 @@
}
}
- static void reject(Runnable r, Class<? extends Exception> extype) {
- try {
- r.run();
- throw new RuntimeException("Expected: " + extype);
- } catch (Throwable t) {
- if (!extype.isAssignableFrom(t.getClass())) {
- throw new RuntimeException("Wrong exception type: " + extype + " / "
- +t.getClass());
- }
- }
- }
-
- static void accept(Runnable r) {
- try {
- r.run();
- } catch (Throwable t) {
- throw new RuntimeException("Unexpected exception: " + t);
- }
- }
-
static void checkNonNull(Supplier<?> r) {
if (r.get() == null)
throw new RuntimeException("Unexpected null return:");
@@ -108,12 +89,14 @@
System.out.println("Test 1");
HttpClient.Builder cb = HttpClient.create();
InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000);
- reject(() -> { cb.priority(-1);}, IllegalArgumentException.class);
- reject(() -> { cb.priority(500);}, IllegalArgumentException.class);
- accept(() -> { cb.priority(1);});
- accept(() -> { cb.priority(255);});
-
- accept(() -> {clients.add(cb.build()); clients.add(cb.build());});
+ TestKit.assertThrows(IllegalArgumentException.class, () -> cb.priority(-1));
+ TestKit.assertThrows(IllegalArgumentException.class, () -> cb.priority(500));
+ TestKit.assertNotThrows(() -> cb.priority(1));
+ TestKit.assertNotThrows(() -> cb.priority(255));
+ TestKit.assertNotThrows(() -> {
+ clients.add(cb.build());
+ clients.add(cb.build());
+ });
}
static void test2() throws Exception {
@@ -139,7 +122,7 @@
static void test3() throws Exception {
System.out.println("Test 3");
- reject(()-> {
+ TestKit.assertThrows(IllegalStateException.class, ()-> {
try {
HttpRequest r1 = request();
HttpResponse resp = r1.response();
@@ -147,9 +130,9 @@
} catch (IOException |InterruptedException e) {
throw new RuntimeException(e);
}
- }, IllegalStateException.class);
+ });
- reject(()-> {
+ TestKit.assertThrows(IllegalStateException.class, ()-> {
try {
HttpRequest r1 = request();
HttpResponse resp = r1.response();
@@ -157,8 +140,8 @@
} catch (IOException |InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
- }, IllegalStateException.class);
- reject(()-> {
+ });
+ TestKit.assertThrows(IllegalStateException.class, ()-> {
try {
HttpRequest r1 = request();
HttpResponse resp1 = r1.responseAsync().get();
@@ -166,7 +149,7 @@
} catch (IOException |InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
- }, IllegalStateException.class);
+ });
}
static class Auth extends java.net.Authenticator {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/EchoHandler.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * 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 com.sun.net.httpserver.*;
+import java.net.*;
+import java.net.http.*;
+import java.io.*;
+import java.util.concurrent.*;
+import javax.net.ssl.*;
+import java.nio.file.*;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import jdk.testlibrary.SimpleSSLContext;
+import static java.net.http.HttpRequest.*;
+import static java.net.http.HttpResponse.*;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class EchoHandler implements HttpHandler {
+ public EchoHandler() {}
+
+ @Override
+ public void handle(HttpExchange t)
+ throws IOException {
+ try {
+ System.err.println("EchoHandler received request to " + t.getRequestURI());
+ InputStream is = t.getRequestBody();
+ Headers map = t.getRequestHeaders();
+ Headers map1 = t.getResponseHeaders();
+ map1.add("X-Hello", "world");
+ map1.add("X-Bye", "universe");
+ String fixedrequest = map.getFirst("XFixed");
+ File outfile = File.createTempFile("foo", "bar");
+ FileOutputStream fos = new FileOutputStream(outfile);
+ int count = (int) is.transferTo(fos);
+ is.close();
+ fos.close();
+ InputStream is1 = new FileInputStream(outfile);
+ OutputStream os = null;
+ // return the number of bytes received (no echo)
+ String summary = map.getFirst("XSummary");
+ if (fixedrequest != null && summary == null) {
+ t.sendResponseHeaders(200, count);
+ os = t.getResponseBody();
+ is1.transferTo(os);
+ } else {
+ t.sendResponseHeaders(200, 0);
+ os = t.getResponseBody();
+ is1.transferTo(os);
+
+ if (summary != null) {
+ String s = Integer.toString(count);
+ os.write(s.getBytes());
+ }
+ }
+ outfile.delete();
+ os.close();
+ is1.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new IOException(e);
+ }
+ }
+}
--- a/jdk/test/java/net/httpclient/LightWeightHttpServer.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java Fri May 06 06:23:30 2016 -0700
@@ -22,10 +22,10 @@
*/
/**
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer
- * @compile ../../../com/sun/net/httpserver/LogFilter.java
- * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
+ * library /lib/testlibrary/ /
+ * build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
+ * compile ../../../com/sun/net/httpserver/LogFilter.java
+ * compile ../../../com/sun/net/httpserver/FileServerHandler.java
*/
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
--- a/jdk/test/java/net/httpclient/ManyRequests.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/ManyRequests.java Fri May 06 06:23:30 2016 -0700
@@ -24,18 +24,17 @@
/**
* @test
* @bug 8087112
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext
+ * @library /lib/testlibrary/ /
+ * @build jdk.testlibrary.SimpleSSLContext EchoHandler
* @compile ../../../com/sun/net/httpserver/LogFilter.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
- * @run main/othervm ManyRequests
+ * @run main/othervm/timeout=40 -Djava.net.http.HttpClient.log=ssl ManyRequests
* @summary Send a large number of requests asynchronously
*/
//package javaapplication16;
-import com.sun.net.httpserver.HttpsConfigurator;
-import com.sun.net.httpserver.HttpsServer;
+import com.sun.net.httpserver.*;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.http.HttpClient;
@@ -47,18 +46,25 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Random;
+import java.util.logging.*;
import java.util.concurrent.CompletableFuture;
-import javax.net.ssl.SSLContext;
+import javax.net.ssl.*;
import jdk.testlibrary.SimpleSSLContext;
public class ManyRequests {
+ volatile static int counter = 0;
+
public static void main(String[] args) throws Exception {
+ Logger logger = Logger.getLogger("com.sun.net.httpserver");
+ logger.setLevel(Level.ALL);
+ logger.info("TEST");
+
SSLContext ctx = new SimpleSSLContext().get();
InetSocketAddress addr = new InetSocketAddress(0);
HttpsServer server = HttpsServer.create(addr, 0);
- server.setHttpsConfigurator(new HttpsConfigurator(ctx));
+ server.setHttpsConfigurator(new Configurator(ctx));
HttpClient client = HttpClient.create()
.sslContext(ctx)
@@ -72,7 +78,8 @@
}
}
- static final int REQUESTS = 1000;
+ //static final int REQUESTS = 1000;
+ static final int REQUESTS = 20;
static void test(HttpsServer server, HttpClient client) throws Exception {
int port = server.getAddress().getPort();
@@ -102,6 +109,9 @@
resp.bodyAsync(HttpResponse.ignoreBody());
String s = "Expected 200, got: " + resp.statusCode();
return completedWithIOException(s);
+ } else {
+ counter++;
+ System.out.println("Result from " + counter);
}
return resp.bodyAsync(HttpResponse.asByteArray())
.thenApply((b) -> new Pair<>(resp, b));
@@ -114,14 +124,18 @@
});
}
+
// wait for them all to complete and throw exception in case of error
- CompletableFuture.allOf(results).join();
+ //try {
+ CompletableFuture.allOf(results).join();
+ //} catch (Exception e) {
+ //e.printStackTrace();
+ //throw e;
+ //}
}
static <T> CompletableFuture<T> completedWithIOException(String message) {
- CompletableFuture<T> cf = new CompletableFuture<>();
- cf.completeExceptionally(new IOException(message));
- return cf;
+ return CompletableFuture.failedFuture(new IOException(message));
}
static final class Pair<T,U> {
@@ -192,3 +206,14 @@
throw new RuntimeException(sb.toString());
}
}
+
+class Configurator extends HttpsConfigurator {
+ public Configurator(SSLContext ctx) {
+ super(ctx);
+ }
+
+ public void configure (HttpsParameters params) {
+ params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+ }
+}
+
--- a/jdk/test/java/net/httpclient/RequestBodyTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/RequestBodyTest.java Fri May 06 06:23:30 2016 -0700
@@ -23,10 +23,11 @@
/**
* @test @bug 8087112
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer
+ * @library /lib/testlibrary/ /
* @compile ../../../com/sun/net/httpserver/LogFilter.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
+ * @build LightWeightHttpServer
+ * @build jdk.testlibrary.SimpleSSLContext ProxyServer
* @run main/othervm RequestBodyTest
*/
--- a/jdk/test/java/net/httpclient/SmokeTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/SmokeTest.java Fri May 06 06:23:30 2016 -0700
@@ -24,15 +24,13 @@
/**
* @test
* @bug 8087112
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer
+ * @library /lib/testlibrary/ /
+ * @build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
* @compile ../../../com/sun/net/httpserver/LogFilter.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @run main/othervm SmokeTest
*/
-//package javaapplication16;
-
import com.sun.net.httpserver.*;
import java.net.*;
import java.net.http.*;
@@ -69,6 +67,7 @@
*/
public class SmokeTest {
static SSLContext ctx;
+ static SSLParameters sslparams;
static HttpServer s1 ;
static HttpsServer s2;
static ExecutorService executor;
@@ -107,6 +106,7 @@
client = HttpClient.create()
.sslContext(ctx)
+ .sslParameters(sslparams)
.followRedirects(HttpClient.Redirect.ALWAYS)
.executorService(Executors.newCachedThreadPool())
.build();
@@ -285,6 +285,7 @@
HttpClient cl = HttpClient.create()
.proxy(ProxySelector.of(proxyAddr))
.sslContext(ctx)
+ .sslParameters(sslparams)
.build();
CompletableFuture<String> fut = cl.request(uri)
@@ -672,7 +673,8 @@
s1.setExecutor(executor);
s2.setExecutor(executor);
ctx = new SimpleSSLContext().get();
- s2.setHttpsConfigurator(new HttpsConfigurator(ctx));
+ sslparams = ctx.getSupportedSSLParameters();
+ s2.setHttpsConfigurator(new Configurator(ctx));
s1.start();
s2.start();
@@ -689,6 +691,16 @@
}
}
+class Configurator extends HttpsConfigurator {
+ public Configurator(SSLContext ctx) {
+ super(ctx);
+ }
+
+ public void configure (HttpsParameters params) {
+ params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+ }
+}
+
class UploadServer extends Thread {
int statusCode;
ServerSocket ss;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/TestKit.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,101 @@
+/*
+ * 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.util.regex.Pattern;
+
+import static java.util.Objects.requireNonNull;
+
+//
+// A set of testing utility functions
+//
+public final class TestKit {
+
+ private TestKit() { }
+
+ public static void assertNotThrows(ThrowingProcedure code) {
+ requireNonNull(code, "code");
+ assertNotThrows(() -> {
+ code.run();
+ return null;
+ });
+ }
+
+ public static <V> V assertNotThrows(ThrowingFunction<V> code) {
+ requireNonNull(code, "code");
+ try {
+ return code.run();
+ } catch (Throwable t) {
+ throw new RuntimeException("Expected to run normally, but threw "
+ + t.getClass().getCanonicalName(), t);
+ }
+ }
+
+ public static <T extends Throwable> T assertThrows(Class<? extends T> clazz,
+ ThrowingProcedure code) {
+ requireNonNull(clazz, "clazz");
+ requireNonNull(code, "code");
+ try {
+ code.run();
+ } catch (Throwable t) {
+ if (clazz.isInstance(t)) {
+ return clazz.cast(t);
+ }
+ throw new RuntimeException("Expected to catch an exception of type "
+ + clazz.getCanonicalName() + ", but caught "
+ + t.getClass().getCanonicalName(), t);
+
+ }
+ throw new RuntimeException("Expected to catch an exception of type "
+ + clazz.getCanonicalName() + ", but caught nothing");
+ }
+
+ public interface ThrowingProcedure {
+ void run() throws Throwable;
+ }
+
+ public interface ThrowingFunction<V> {
+ V run() throws Throwable;
+ }
+
+ // The rationale behind asking for a regex is to not pollute variable names
+ // space in the scope of assertion: if it's something as simple as checking
+ // a message, we can do it inside
+ public static <T extends Throwable> T assertThrows(Class<? extends T> clazz,
+ String messageRegex,
+ ThrowingProcedure code) {
+ requireNonNull(messageRegex, "messagePattern");
+ T t = assertThrows(clazz, code);
+ String m = t.getMessage();
+ if (m == null) {
+ throw new RuntimeException(String.format(
+ "Expected exception message to match the regex '%s', " +
+ "but the message was null", messageRegex), t);
+ }
+ if (!Pattern.matches(messageRegex, m)) {
+ throw new RuntimeException(String.format(
+ "Expected exception message to match the regex '%s', " +
+ "actual message: %s", messageRegex, m), t);
+ }
+ return t;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/TestKitTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,130 @@
+/*
+ * 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.IOException;
+import java.util.IllegalFormatException;
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @compile TestKit.java
+ * @run testng TestKitTest
+ */
+public final class TestKitTest {
+
+ public static void main(String[] args) {
+ testAssertNotThrows();
+ testAssertThrows();
+ }
+
+ private static void testAssertNotThrows() {
+ Integer integer = TestKit.assertNotThrows(
+ () -> TestKit.assertNotThrows(() -> 1)
+ );
+ assertEquals(integer, Integer.valueOf(1));
+
+ RuntimeException re = TestKit.assertThrows(
+ RuntimeException.class,
+ () -> TestKit.assertNotThrows(() -> { throw new IOException(); })
+ );
+ assertEquals(re.getMessage(),
+ "Expected to run normally, but threw "
+ + "java.io.IOException");
+
+ TestKit.assertNotThrows(
+ () -> TestKit.assertNotThrows(() -> { })
+ );
+
+ re = TestKit.assertThrows(
+ RuntimeException.class,
+ () -> TestKit.assertNotThrows((TestKit.ThrowingProcedure) () -> { throw new IOException(); })
+ );
+ assertEquals(re.getMessage(),
+ "Expected to run normally, but threw "
+ + "java.io.IOException");
+ }
+
+ private static void testAssertThrows() {
+ NullPointerException npe = TestKit.assertThrows(
+ NullPointerException.class,
+ () -> TestKit.assertThrows(null, null)
+ );
+ assertNotNull(npe);
+ assertTrue(Set.of("clazz", "code").contains(npe.getMessage()), npe.getMessage());
+
+ npe = TestKit.assertThrows(
+ NullPointerException.class,
+ () -> TestKit.assertThrows(IOException.class, null)
+ );
+ assertNotNull(npe);
+ assertEquals(npe.getMessage(), "code");
+
+ npe = TestKit.assertThrows(
+ NullPointerException.class,
+ () -> TestKit.assertThrows(null, () -> { })
+ );
+ assertEquals(npe.getMessage(), "clazz");
+
+ npe = TestKit.assertThrows(
+ NullPointerException.class,
+ () -> { throw new NullPointerException(); }
+ );
+ assertNotNull(npe);
+ assertNull(npe.getMessage());
+ assertEquals(npe.getClass(), NullPointerException.class);
+
+ RuntimeException re = TestKit.assertThrows(
+ RuntimeException.class,
+ () -> TestKit.assertThrows(NullPointerException.class, () -> { })
+ );
+ assertEquals(re.getClass(), RuntimeException.class);
+ assertEquals(re.getMessage(),
+ "Expected to catch an exception of type "
+ + "java.lang.NullPointerException, but caught nothing");
+
+ re = TestKit.assertThrows(
+ RuntimeException.class,
+ () -> { throw new NullPointerException(); }
+ );
+ assertNotNull(re);
+ assertNull(re.getMessage());
+ assertEquals(re.getClass(), NullPointerException.class);
+
+ re = TestKit.assertThrows(
+ RuntimeException.class,
+ () -> TestKit.assertThrows(
+ IllegalFormatException.class,
+ () -> { throw new IndexOutOfBoundsException(); }
+ ));
+ assertNotNull(re);
+ assertEquals(re.getClass(), RuntimeException.class);
+ assertEquals(re.getMessage(),
+ "Expected to catch an exception of type java.util.IllegalFormatException"
+ + ", but caught java.lang.IndexOutOfBoundsException");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/BasicTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,222 @@
+/*
+ * 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
+ * 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 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @modules java.httpclient
+ * @compile/module=java.httpclient java/net/http/BodyOutputStream.java
+ * @compile/module=java.httpclient java/net/http/BodyInputStream.java
+ * @compile/module=java.httpclient java/net/http/EchoHandler.java
+ * @compile/module=java.httpclient java/net/http/Http2Handler.java
+ * @compile/module=java.httpclient java/net/http/Http2TestExchange.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServer.java
+ * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java
+ * @compile/module=java.httpclient java/net/http/TestUtil.java
+ * @run testng/othervm -Djava.net.http.HttpClient.log=ssl,requests,responses,errors BasicTest
+ */
+
+import java.io.*;
+import java.net.*;
+import java.net.http.*;
+import static java.net.http.HttpClient.Version.HTTP_2;
+import javax.net.ssl.*;
+import java.nio.file.*;
+import java.util.concurrent.*;
+import jdk.testlibrary.SimpleSSLContext;
+
+
+import org.testng.annotations.Test;
+import org.testng.annotations.Parameters;
+
+@Test
+public class BasicTest {
+ static int httpPort, httpsPort;
+ static Http2TestServer httpServer, httpsServer;
+ static HttpClient client = null;
+ static ExecutorService exec;
+ static SSLContext sslContext;
+
+ static String httpURIString, httpsURIString;
+
+ static void initialize() throws Exception {
+ try {
+ SimpleSSLContext sslct = new SimpleSSLContext();
+ sslContext = sslct.get();
+ client = getClient();
+ exec = client.executorService();
+ httpServer = new Http2TestServer(false, 0, new EchoHandler(),
+ exec, sslContext);
+ httpPort = httpServer.getAddress().getPort();
+
+ httpsServer = new Http2TestServer(true, 0, new EchoHandler(),
+ exec, sslContext);
+
+ httpsPort = httpsServer.getAddress().getPort();
+ httpURIString = "http://127.0.0.1:" + Integer.toString(httpPort) +
+ "/foo/";
+ httpsURIString = "https://127.0.0.1:" + Integer.toString(httpsPort) +
+ "/bar/";
+
+ httpServer.start();
+ httpsServer.start();
+ } catch (Throwable e) {
+ System.err.println("Throwing now");
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ @Test(timeOut=30000)
+ public static void test() throws Exception {
+ try {
+ initialize();
+ simpleTest(false);
+ simpleTest(true);
+ streamTest(false);
+ streamTest(true);
+ Thread.sleep(1000 * 4);
+ } finally {
+ httpServer.stop();
+ httpsServer.stop();
+ exec.shutdownNow();
+ }
+ }
+
+ static HttpClient getClient() {
+ if (client == null) {
+ client = HttpClient.create()
+ .sslContext(sslContext)
+ .version(HTTP_2)
+ .build();
+ }
+ return client;
+ }
+
+ static URI getURI(boolean secure) {
+ if (secure)
+ return URI.create(httpsURIString);
+ else
+ return URI.create(httpURIString);
+ }
+
+ static void checkStatus(int expected, int found) throws Exception {
+ if (expected != found) {
+ System.err.printf ("Test failed: wrong status code %d/%d\n",
+ expected, found);
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ static void checkStrings(String expected, String found) throws Exception {
+ if (!expected.equals(found)) {
+ System.err.printf ("Test failed: wrong string %s/%s\n",
+ expected, found);
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ static Void compareFiles(Path path1, Path path2) {
+ return java.net.http.TestUtil.compareFiles(path1, path2);
+ }
+
+ static Path tempFile() {
+ return java.net.http.TestUtil.tempFile();
+ }
+
+ static final String SIMPLE_STRING = "Hello world Goodbye world";
+
+ static final int LOOPS = 13;
+ static final int FILESIZE = 64 * 1024;
+
+ static void streamTest(boolean secure) throws Exception {
+ URI uri = getURI(secure);
+ System.err.printf("streamTest %b to %s\n" , secure, uri);
+
+ HttpClient client = getClient();
+ Path src = java.net.http.TestUtil.getAFile(FILESIZE * 4);
+ HttpRequest req = client.request(uri)
+ .body(HttpRequest.fromFile(src))
+ .POST();
+
+ CompletableFuture<InputStream> response = req.responseAsync()
+ .thenCompose(resp -> {
+ if (resp.statusCode() != 200)
+ throw new RuntimeException();
+ return resp.bodyAsync(HttpResponse.asInputStream());
+ });
+ InputStream is = response.join();
+ File dest = File.createTempFile("foo","bar");
+ dest.deleteOnExit();
+ FileOutputStream os = new FileOutputStream(dest);
+ is.transferTo(os);
+ is.close();
+ os.close();
+ int count = 0;
+ compareFiles(src, dest.toPath());
+ System.err.println("DONE");
+ }
+
+
+ static void simpleTest(boolean secure) throws Exception {
+ URI uri = getURI(secure);
+ System.err.println("Request to " + uri);
+
+ // Do a simple warmup request
+
+ HttpClient client = getClient();
+ HttpRequest req = client.request(uri)
+ .body(HttpRequest.fromString(SIMPLE_STRING))
+ .POST();
+ HttpResponse response = req.response();
+ HttpHeaders h = response.headers();
+
+ checkStatus(200, response.statusCode());
+
+ String responseBody = response.body(HttpResponse.asString());
+ checkStrings(SIMPLE_STRING, responseBody);
+
+ checkStrings(h.firstValue("x-hello").get(), "world");
+ checkStrings(h.firstValue("x-bye").get(), "universe");
+
+ // Do loops asynchronously
+
+ CompletableFuture[] responses = new CompletableFuture[LOOPS];
+ final Path source = java.net.http.TestUtil.getAFile(FILESIZE);
+ for (int i = 0; i < LOOPS; i++) {
+ responses[i] = client.request(uri)
+ .body(HttpRequest.fromFile(source))
+ .version(HTTP_2)
+ .POST()
+ .responseAsync()
+ .thenCompose(r -> r.bodyAsync(HttpResponse.asFile(tempFile())))
+ .thenApply(path -> compareFiles(path, source));
+ Thread.sleep(100);
+ }
+ CompletableFuture.allOf(responses).join();
+ System.err.println("DONE");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/ServerPush.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,107 @@
+/*
+ * 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
+ * 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 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @modules java.httpclient
+ * @compile/module=java.httpclient java/net/http/BodyOutputStream.java
+ * @compile/module=java.httpclient java/net/http/BodyInputStream.java
+ * @compile/module=java.httpclient java/net/http/PushHandler.java
+ * @compile/module=java.httpclient java/net/http/Http2Handler.java
+ * @compile/module=java.httpclient java/net/http/Http2TestExchange.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServer.java
+ * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java
+ * @compile/module=java.httpclient java/net/http/TestUtil.java
+ * @run testng/othervm -Djava.net.http.HttpClient.log=requests,responses ServerPush
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.http.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.testng.annotations.Test;
+
+public class ServerPush {
+
+ static ExecutorService e = Executors.newCachedThreadPool();
+
+ static final int LOOPS = 13;
+ static final int FILE_SIZE = 32 * 1024;
+
+ static Path tempFile;
+
+ @Test(timeOut=30000)
+ public static void test() throws Exception {
+ Http2TestServer server = null;
+ Path dir = null;
+ try {
+ server = new Http2TestServer(false, 0,
+ new PushHandler(FILE_SIZE, LOOPS));
+ tempFile = TestUtil.getAFile(FILE_SIZE);
+
+ System.err.println("Server listening on port " + server.getAddress().getPort());
+ server.start();
+ int port = server.getAddress().getPort();
+ dir = Files.createTempDirectory("serverPush");
+
+ URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/foo");
+ HttpRequest request = HttpRequest.create(uri)
+ .version(HttpClient.Version.HTTP_2)
+ .GET();
+
+ CompletableFuture<Map<URI,Path>> cf =
+ request.multiResponseAsync(HttpResponse.multiFile(dir));
+ Map<URI,Path> results = cf.get();
+
+ //HttpResponse resp = request.response();
+ System.err.println(results.size());
+ Set<URI> uris = results.keySet();
+ for (URI u : uris) {
+ Path result = results.get(u);
+ System.err.printf("%s -> %s\n", u.toString(), result.toString());
+ TestUtil.compareFiles(result, tempFile);
+ }
+ System.out.println("TEST OK");
+ } finally {
+ e.shutdownNow();
+ server.stop();
+ Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+ dir.toFile().delete();
+ return FileVisitResult.CONTINUE;
+ }
+ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
+ path.toFile().delete();
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/TEST.properties Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,1 @@
+bootclasspath.dirs = /java/net/httpclient
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyInputStream.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,107 @@
+package java.net.http;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+/**
+ * InputStream reads frames off stream q and supplies read demand from any
+ * DataFrames it finds. Window updates are sent back on the connections send
+ * q.
+ */
+class BodyInputStream extends InputStream {
+
+ final Queue<Http2Frame> q;
+ final int streamid;
+ boolean closed;
+ boolean eof;
+ final Http2TestServerConnection conn;
+
+ @SuppressWarnings({"rawtypes","unchecked"})
+ BodyInputStream(Queue q, int streamid, Http2TestServerConnection conn) {
+ this.q = q;
+ this.streamid = streamid;
+ this.conn = conn;
+ }
+
+ DataFrame df;
+ ByteBuffer[] buffers;
+ ByteBuffer buffer;
+ int nextIndex = -1;
+
+ private DataFrame getData() throws IOException {
+ if (eof) {
+ return null;
+ }
+ Http2Frame frame;
+ do {
+ frame = q.take();
+ if (frame.type() == ResetFrame.TYPE) {
+ conn.handleStreamReset((ResetFrame) frame); // throws IOException
+ }
+ // ignoring others for now Wupdates handled elsewhere
+ if (frame.type() != DataFrame.TYPE) {
+ System.out.println("Ignoring " + frame.toString() + " CHECK THIS");
+ }
+ } while (frame.type() != DataFrame.TYPE);
+ df = (DataFrame) frame;
+ int len = df.getDataLength();
+ eof = frame.getFlag(DataFrame.END_STREAM);
+ // acknowledge
+ conn.sendWindowUpdates(len, streamid);
+ return (DataFrame) frame;
+ }
+
+ // null return means EOF
+ private ByteBuffer getBuffer() throws IOException {
+ if (buffer == null || !buffer.hasRemaining()) {
+ if (nextIndex == -1 || nextIndex == buffers.length) {
+ DataFrame df = getData();
+ if (df == null) {
+ return null;
+ }
+ int len = df.getDataLength();
+ if ((len == 0) && eof) {
+ return null;
+ }
+ buffers = df.getData();
+ nextIndex = 0;
+ }
+ buffer = buffers[nextIndex++];
+ }
+ return buffer;
+ }
+
+ @Override
+ public int read(byte[] buf, int offset, int length) throws IOException {
+ if (closed) {
+ throw new IOException("closed");
+ }
+ ByteBuffer b = getBuffer();
+ if (b == null) {
+ return -1;
+ }
+ int remaining = b.remaining();
+ if (remaining < length) {
+ length = remaining;
+ }
+ b.get(buf, offset, length);
+ return length;
+ }
+
+ byte[] one = new byte[1];
+
+ @Override
+ public int read() throws IOException {
+ int c = read(one, 0, 1);
+ if (c == -1) {
+ return -1;
+ }
+ return one[0];
+ }
+
+ @Override
+ public void close() {
+ // TODO reset this stream
+ closed = true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyOutputStream.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,106 @@
+package java.net.http;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+/**
+ * OutputStream. Incoming window updates handled by the main connection
+ * reader thread.
+ */
+@SuppressWarnings({"rawtypes","unchecked"})
+class BodyOutputStream extends OutputStream {
+ final static byte[] EMPTY_BARRAY = new byte[0];
+
+ final int streamid;
+ int window;
+ boolean closed;
+ boolean goodToGo = false; // not allowed to send until headers sent
+ final Http2TestServerConnection conn;
+ final Queue outputQ;
+
+ BodyOutputStream(int streamid, int initialWindow, Http2TestServerConnection conn) {
+ this.window = initialWindow;
+ this.streamid = streamid;
+ this.conn = conn;
+ this.outputQ = conn.outputQ;
+ conn.registerStreamWindowUpdater(streamid, this::updateWindow);
+ }
+
+ // called from connection reader thread as all incoming window
+ // updates are handled there.
+ synchronized void updateWindow(int update) {
+ window += update;
+ notifyAll();
+ }
+
+ void waitForWindow(int demand) throws InterruptedException {
+ // first wait for the connection window
+ conn.obtainConnectionWindow(demand);
+ // now wait for the stream window
+ synchronized (this) {
+ while (demand > 0) {
+ int n = Math.min(demand, window);
+ demand -= n;
+ window -= n;
+ if (demand > 0) {
+ wait();
+ }
+ }
+ }
+ }
+
+ void goodToGo() {
+ goodToGo = true;
+ }
+
+ @Override
+ public void write(byte[] buf, int offset, int len) throws IOException {
+ if (closed) {
+ throw new IOException("closed");
+ }
+
+ if (!goodToGo) {
+ throw new IllegalStateException("sendResponseHeaders must be called first");
+ }
+ try {
+ waitForWindow(len);
+ send(buf, offset, len, 0);
+ } catch (InterruptedException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ private void send(byte[] buf, int offset, int len, int flags) throws IOException {
+ ByteBuffer buffer = ByteBuffer.allocate(len);
+ buffer.put(buf, offset, len);
+ buffer.flip();
+ DataFrame df = new DataFrame();
+ assert streamid != 0;
+ df.streamid(streamid);
+ df.setFlags(flags);
+ df.setData(buffer);
+ outputQ.put(df);
+ }
+
+ byte[] one = new byte[1];
+
+ @Override
+ public void write(int b) throws IOException {
+ one[0] = (byte) b;
+ write(one, 0, 1);
+ }
+
+ @Override
+ public void close() {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ try {
+ send(EMPTY_BARRAY, 0, 0, DataFrame.END_STREAM);
+ } catch (IOException ex) {
+ System.err.println("TestServer: OutputStream.close exception: " + ex);
+ ex.printStackTrace();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/EchoHandler.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005, 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 java.net.http;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+import java.net.*;
+
+public class EchoHandler implements Http2Handler {
+ public EchoHandler() {}
+
+ @Override
+ public void handle(Http2TestExchange t)
+ throws IOException {
+ try {
+ System.err.println("EchoHandler received request to " + t.getRequestURI());
+ InputStream is = t.getRequestBody();
+ HttpHeadersImpl map = t.getRequestHeaders();
+ HttpHeadersImpl map1 = t.getResponseHeaders();
+ map1.addHeader("X-Hello", "world");
+ map1.addHeader("X-Bye", "universe");
+ String fixedrequest = map.firstValue("XFixed").orElse(null);
+ File outfile = File.createTempFile("foo", "bar");
+ FileOutputStream fos = new FileOutputStream(outfile);
+ int count = (int) is.transferTo(fos);
+ System.err.printf("EchoHandler read %d bytes\n", count);
+ is.close();
+ fos.close();
+ InputStream is1 = new FileInputStream(outfile);
+ OutputStream os = null;
+ // return the number of bytes received (no echo)
+ String summary = map.firstValue("XSummary").orElse(null);
+ if (fixedrequest != null && summary == null) {
+ t.sendResponseHeaders(200, count);
+ os = t.getResponseBody();
+ is1.transferTo(os);
+ } else {
+ t.sendResponseHeaders(200, 0);
+ os = t.getResponseBody();
+ int count1 = (int)is1.transferTo(os);
+ System.err.printf("EchoHandler wrote %d bytes\n", count1);
+
+ if (summary != null) {
+ String s = Integer.toString(count);
+ os.write(s.getBytes());
+ }
+ }
+ outfile.delete();
+ os.close();
+ is1.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new IOException(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2Handler.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,18 @@
+package java.net.http;
+
+import java.io.IOException;
+
+/**
+ * A handler which is invoked to process HTTP exchanges. Each
+ * HTTP exchange is handled by one of these handlers.
+ */
+public interface Http2Handler {
+ /**
+ * Handle the given request and generate an appropriate response.
+ * @param exchange the exchange containing the request from the
+ * client and used to send the response
+ * @throws NullPointerException if exchange is <code>null</code>
+ */
+ public abstract void handle (Http2TestExchange exchange) throws IOException;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestExchange.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,126 @@
+package java.net.http;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.InetSocketAddress;
+
+public class Http2TestExchange {
+
+ final HttpHeadersImpl reqheaders;
+ final HttpHeadersImpl rspheaders;
+ final URI uri;
+ final String method;
+ final InputStream is;
+ final BodyOutputStream os;
+ final int streamid;
+ final boolean pushAllowed;
+ final Http2TestServerConnection conn;
+ final Http2TestServer server;
+
+ int responseCode = -1;
+ long responseLength;
+
+ Http2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders,
+ HttpHeadersImpl rspheaders, URI uri, InputStream is,
+ BodyOutputStream os, Http2TestServerConnection conn, boolean pushAllowed) {
+ this.reqheaders = reqheaders;
+ this.rspheaders = rspheaders;
+ this.uri = uri;
+ this.method = method;
+ this.is = is;
+ this.streamid = streamid;
+ this.os = os;
+ this.pushAllowed = pushAllowed;
+ this.conn = conn;
+ this.server = conn.server;
+ }
+
+ public HttpHeadersImpl getRequestHeaders() {
+ return reqheaders;
+ }
+
+ public HttpHeadersImpl getResponseHeaders() {
+ return rspheaders;
+ }
+
+ public URI getRequestURI() {
+ return uri;
+ }
+
+ public String getRequestMethod() {
+ return method;
+ }
+
+ public void close() {
+ try {
+ is.close();
+ os.close();
+ } catch (IOException e) {
+ System.err.println("TestServer: HttpExchange.close exception: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ public InputStream getRequestBody() {
+ return is;
+ }
+
+ public OutputStream getResponseBody() {
+ return os;
+ }
+
+ public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
+ this.responseLength = responseLength;
+ if (responseLength > 0 || responseLength < 0) {
+ long clen = responseLength > 0 ? responseLength : 0;
+ rspheaders.setHeader("Content-length", Long.toString(clen));
+ }
+
+ rspheaders.setHeader(":status", Integer.toString(rCode));
+
+ Http2TestServerConnection.ResponseHeaders response
+ = new Http2TestServerConnection.ResponseHeaders(rspheaders);
+ response.streamid(streamid);
+ response.setFlag(HeaderFrame.END_HEADERS);
+ conn.outputQ.put(response);
+ os.goodToGo();
+ System.err.println("Sent response headers " + rCode);
+ }
+
+ public InetSocketAddress getRemoteAddress() {
+ return (InetSocketAddress) conn.socket.getRemoteSocketAddress();
+ }
+
+ public int getResponseCode() {
+ return responseCode;
+ }
+
+ public InetSocketAddress getLocalAddress() {
+ return server.getAddress();
+ }
+
+ public String getProtocol() {
+ return "HTTP/2";
+ }
+
+ public boolean serverPushAllowed() {
+ return pushAllowed;
+ }
+
+ public void serverPush(URI uri, HttpHeadersImpl headers, InputStream content) {
+ OutgoingPushPromise pp = new OutgoingPushPromise(
+ streamid, uri, headers, content);
+ headers.setHeader(":method", "GET");
+ headers.setHeader(":scheme", uri.getScheme());
+ headers.setHeader(":authority", uri.getAuthority());
+ headers.setHeader(":path", uri.getPath());
+ try {
+ conn.outputQ.put(pp);
+ // writeLoop will spin up thread to read the InputStream
+ } catch (IOException ex) {
+ System.err.println("TestServer: pushPromise exception: " + ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,159 @@
+/*
+ * 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
+ * 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 java.net.http;
+
+import java.io.IOException;
+import java.net.*;
+import java.util.HashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+
+/**
+ * Waits for incoming TCP connections from a client and establishes
+ * a HTTP2 connection. Two threads are created per connection. One for reading
+ * and one for writing. Incoming requests are dispatched to the supplied
+ * Http2Handler on additional threads. All threads
+ * obtained from the supplied ExecutorService.
+ */
+public class Http2TestServer {
+ final ServerSocket server;
+ boolean secure;
+ SettingsFrame serverSettings, clientSettings;
+ final ExecutorService exec;
+ volatile boolean stopping = false;
+ final Http2Handler handler;
+ final SSLContext sslContext;
+ final HashMap<InetSocketAddress,Http2TestServerConnection> connections;
+
+ private static ThreadFactory defaultThreadFac =
+ (Runnable r) -> {
+ Thread t = new Thread(r);
+ t.setName("Test-server-pool");
+ return t;
+ };
+
+
+ private static ExecutorService getDefaultExecutor() {
+ return Executors.newCachedThreadPool(defaultThreadFac);
+ }
+
+ public Http2TestServer(boolean secure, int port, Http2Handler handler) throws Exception {
+ this(secure, port, handler, getDefaultExecutor(), null);
+ }
+
+ public InetSocketAddress getAddress() {
+ return (InetSocketAddress)server.getLocalSocketAddress();
+ }
+
+ /**
+ * Create a Http2Server listening on the given port. Currently needs
+ * to know in advance whether incoming connections are plain TCP "h2c"
+ * or TLS "h2"/
+ *
+ * @param secure https or http
+ * @param port listen port
+ * @param handler the handler which receives incoming requests
+ * @param exec executor service (cached thread pool is used if null)
+ * @param context the SSLContext used when secure is true
+ * @throws Exception
+ */
+ public Http2TestServer(boolean secure, int port, Http2Handler handler,
+ ExecutorService exec, SSLContext context) throws Exception {
+ if (secure) {
+ server = initSecure(port);
+ } else {
+ server = initPlaintext(port);
+ }
+ this.secure = secure;
+ this.exec = exec == null ? getDefaultExecutor() : exec;
+ this.handler = handler;
+ this.sslContext = context;
+ this.connections = new HashMap<>();
+ }
+
+ final ServerSocket initPlaintext(int port) throws Exception {
+ return new ServerSocket(port);
+ }
+
+ public void stop() {
+ // TODO: clean shutdown GoAway
+ stopping = true;
+ for (Http2TestServerConnection connection : connections.values()) {
+ connection.close();
+ }
+ try {
+ server.close();
+ } catch (IOException e) {}
+ exec.shutdownNow();
+ }
+
+
+ final ServerSocket initSecure(int port) throws Exception {
+ ServerSocketFactory fac;
+ if (sslContext != null) {
+ fac = sslContext.getServerSocketFactory();
+ } else {
+ fac = SSLServerSocketFactory.getDefault();
+ }
+ SSLServerSocket se = (SSLServerSocket) fac.createServerSocket(port);
+ SSLParameters sslp = se.getSSLParameters();
+ sslp.setApplicationProtocols(new String[]{"h2"});
+ se.setSSLParameters(sslp);
+ se.setEnabledCipherSuites(se.getSupportedCipherSuites());
+ se.setEnabledProtocols(se.getSupportedProtocols());
+ // other initialisation here
+ return se;
+ }
+
+ /**
+ * Start thread which waits for incoming connections.
+ *
+ * @throws Exception
+ */
+ public void start() {
+ exec.submit(() -> {
+ try {
+ while (!stopping) {
+ Socket socket = server.accept();
+ InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
+ Http2TestServerConnection c = new Http2TestServerConnection(this, socket);
+ connections.put(addr, c);
+ c.run();
+ }
+ } catch (Throwable e) {
+ if (!stopping) {
+ System.err.println("TestServer: start exception: " + e);
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServerConnection.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,730 @@
+/*
+ * 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
+ * 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 java.net.http;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+import sun.net.httpclient.hpack.Decoder;
+import sun.net.httpclient.hpack.DecodingCallback;
+import sun.net.httpclient.hpack.Encoder;
+
+/**
+ * Represents one HTTP2 connection, either plaintext upgraded from HTTP/1.1
+ * or HTTPS opened using "h2" ALPN.
+ */
+public class Http2TestServerConnection {
+ final Http2TestServer server;
+ @SuppressWarnings({"rawtypes","unchecked"})
+ final Map<Integer, Queue> streams; // input q per stream
+ final Queue<Http2Frame> outputQ;
+ int nextstream;
+ final Socket socket;
+ final InputStream is;
+ final OutputStream os;
+ Encoder hpackOut;
+ Decoder hpackIn;
+ SettingsFrame clientSettings, serverSettings;
+ final ExecutorService exec;
+ final boolean secure;
+ final Http2Handler handler;
+ volatile boolean stopping;
+ int nextPushStreamId = 2;
+
+ final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
+ final static byte[] EMPTY_BARRAY = new byte[0];
+
+ final static byte[] clientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes();
+
+ Http2TestServerConnection(Http2TestServer server, Socket socket) throws IOException {
+ System.err.println("New connection from " + socket);
+ this.server = server;
+ this.streams = Collections.synchronizedMap(new HashMap<>());
+ this.outputQ = new Queue<>();
+ this.socket = socket;
+ this.clientSettings = server.clientSettings;
+ this.serverSettings = server.serverSettings;
+ this.exec = server.exec;
+ this.secure = server.secure;
+ this.handler = server.handler;
+ is = new BufferedInputStream(socket.getInputStream());
+ os = new BufferedOutputStream(socket.getOutputStream());
+ }
+
+ void close() {
+ streams.forEach((i, q) -> {
+ q.close();
+ });
+ stopping = true;
+ try {
+ socket.close();
+ // TODO: put a reset on each stream
+ } catch (IOException e) {
+ }
+ }
+
+ private void readPreface() throws IOException {
+ int len = clientPreface.length;
+ byte[] bytes = new byte[len];
+ is.readNBytes(bytes, 0, len);
+ if (Arrays.compare(clientPreface, bytes) != 0) {
+ throw new IOException("Invalid preface: " + new String(bytes, 0, len));
+ }
+ }
+
+ String doUpgrade() throws IOException {
+ String upgrade = readHttp1Request();
+ String h2c = getHeader(upgrade, "Upgrade");
+ if (h2c == null || !h2c.equals("h2c")) {
+ throw new IOException("Bad upgrade 1 " + h2c);
+ }
+
+ sendHttp1Response(101, "Switching Protocols", "Connection", "Upgrade",
+ "Upgrade", "h2c");
+
+ sendSettingsFrame();
+ readPreface();
+
+ String clientSettingsString = getHeader(upgrade, "HTTP2-Settings");
+ clientSettings = getSettingsFromString(clientSettingsString);
+
+ return upgrade;
+ }
+
+ /**
+ * Client settings payload provided in base64 HTTP1 header. Decode it
+ * and add a header so we can interpret it.
+ *
+ * @param s
+ * @return
+ * @throws IOException
+ */
+ private SettingsFrame getSettingsFromString(String s) throws IOException {
+ Base64.Decoder decoder = Base64.getUrlDecoder();
+ byte[] payload = decoder.decode(s);
+ ByteBuffer bb1 = ByteBuffer.wrap(payload);
+ // simulate header of Settings Frame
+ ByteBuffer bb0 = ByteBuffer.wrap(
+ new byte[] {0, 0, (byte)payload.length, 4, 0, 0, 0, 0, 0});
+ ByteBufferConsumer bbc = new ByteBufferConsumer(
+ new LinkedList<ByteBuffer>(List.of(bb0, bb1)),
+ this::getBuffer);
+ Http2Frame frame = Http2Frame.readIncoming(bbc);
+ if (!(frame instanceof SettingsFrame))
+ throw new IOException("Expected SettingsFrame");
+ return (SettingsFrame)frame;
+ }
+
+ void run() throws Exception {
+ String upgrade = null;
+ if (!secure) {
+ upgrade = doUpgrade();
+ } else {
+ readPreface();
+ sendSettingsFrame(true);
+ clientSettings = (SettingsFrame) readFrame();
+ nextstream = 1;
+ }
+
+ hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE));
+ hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
+
+ exec.submit(() -> {
+ readLoop();
+ });
+ exec.submit(() -> {
+ writeLoop();
+ });
+ if (!secure) {
+ createPrimordialStream(upgrade);
+ nextstream = 3;
+ }
+ }
+
+ static class BufferPool implements BufferHandler {
+
+ public void setMinBufferSize(int size) {
+ }
+
+ public ByteBuffer getBuffer(int size) {
+ if (size == -1)
+ size = 32 * 1024;
+ return ByteBuffer.allocate(size);
+ }
+
+ public void returnBuffer(ByteBuffer buffer) {
+ }
+ }
+
+ static BufferPool bufferpool = new BufferPool();
+
+ private void writeFrame(Http2Frame frame) throws IOException {
+ ByteBufferGenerator bg = new ByteBufferGenerator(bufferpool);
+ frame.computeLength();
+ System.err.println("Writing frame " + frame.toString());
+ frame.writeOutgoing(bg);
+ ByteBuffer[] bufs = bg.getBufferArray();
+ int c = 0;
+ for (ByteBuffer buf : bufs) {
+ byte[] ba = buf.array();
+ int start = buf.arrayOffset() + buf.position();
+ c += buf.remaining();
+ os.write(ba, start, buf.remaining());
+ }
+ os.flush();
+ System.err.printf("wrote %d bytes\n", c);
+ }
+
+ void handleStreamReset(ResetFrame resetFrame) throws IOException {
+ // TODO: cleanup
+ throw new IOException("Stream reset");
+ }
+
+ private void handleCommonFrame(Http2Frame f) throws IOException {
+ if (f instanceof SettingsFrame) {
+ serverSettings = (SettingsFrame) f;
+ if (serverSettings.getFlag(SettingsFrame.ACK)) // ignore
+ {
+ return;
+ }
+ // otherwise acknowledge it
+ SettingsFrame frame = new SettingsFrame();
+ frame.setFlag(SettingsFrame.ACK);
+ frame.streamid(0);
+ outputQ.put(frame);
+ return;
+ }
+ System.err.println("Received ---> " + f.toString());
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ void sendWindowUpdates(int len, int streamid) throws IOException {
+ if (len == 0)
+ return;
+ WindowUpdateFrame wup = new WindowUpdateFrame();
+ wup.streamid(streamid);
+ wup.setUpdate(len);
+ outputQ.put(wup);
+ wup = new WindowUpdateFrame();
+ wup.streamid(0);
+ wup.setUpdate(len);
+ outputQ.put(wup);
+ }
+
+ HttpHeadersImpl decodeHeaders(List<HeaderFrame> frames) {
+ HttpHeadersImpl headers = new HttpHeadersImpl();
+
+ DecodingCallback cb = (name, value) -> {
+ headers.addHeader(name.toString(), value.toString());
+ };
+
+ for (HeaderFrame frame : frames) {
+ ByteBuffer[] buffers = frame.getHeaderBlock();
+ for (ByteBuffer buffer : buffers) {
+ hpackIn.decode(buffer, false, cb);
+ }
+ }
+ hpackIn.decode(EMPTY_BUFFER, true, cb);
+ return headers;
+ }
+
+ String getRequestLine(String request) {
+ int eol = request.indexOf(CRLF);
+ return request.substring(0, eol);
+ }
+
+ // First stream (1) comes from a plaintext HTTP/1.1 request
+ @SuppressWarnings({"rawtypes","unchecked"})
+ void createPrimordialStream(String request) throws IOException {
+ HttpHeadersImpl headers = new HttpHeadersImpl();
+ String requestLine = getRequestLine(request);
+ String[] tokens = requestLine.split(" ");
+ if (!tokens[2].equals("HTTP/1.1")) {
+ throw new IOException("bad request line");
+ }
+ URI uri = null;
+ try {
+ uri = new URI(tokens[1]);
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
+ String host = getHeader(request, "Host");
+ if (host == null) {
+ throw new IOException("missing Host");
+ }
+
+ headers.setHeader(":method", tokens[0]);
+ headers.setHeader(":scheme", "http"); // always in this case
+ headers.setHeader(":authority", host);
+ headers.setHeader(":path", uri.getPath());
+ Queue q = new Queue();
+ String body = getRequestBody(request);
+ headers.setHeader("Content-length", Integer.toString(body.length()));
+
+ addRequestBodyToQueue(body, q);
+ streams.put(1, q);
+ exec.submit(() -> {
+ handleRequest(headers, q, 1);
+ });
+ }
+
+ // all other streams created here
+ @SuppressWarnings({"rawtypes","unchecked"})
+ void createStream(HeaderFrame frame) throws IOException {
+ List<HeaderFrame> frames = new LinkedList<>();
+ frames.add(frame);
+ int streamid = frame.streamid();
+ if (streamid != nextstream) {
+ throw new IOException("unexpected stream id");
+ }
+ nextstream += 2;
+
+ while (!frame.getFlag(HeaderFrame.END_HEADERS)) {
+ Http2Frame f = readFrame();
+ if (!(f instanceof HeaderFrame)) {
+ handleCommonFrame(f); // should only be error frames
+ } else {
+ frame = (HeaderFrame) f;
+ frames.add(frame);
+ }
+ }
+ HttpHeadersImpl headers = decodeHeaders(frames);
+ Queue q = new Queue();
+ streams.put(streamid, q);
+ exec.submit(() -> {
+ handleRequest(headers, q, streamid);
+ });
+ }
+
+ // runs in own thread. Handles request from start to finish. Incoming frames
+ // for this stream/request delivered on Q
+
+ @SuppressWarnings({"rawtypes","unchecked"})
+ void handleRequest(HttpHeadersImpl headers, Queue queue, int streamid) {
+ String method = headers.firstValue(":method").orElse("");
+ System.out.println("method = " + method);
+ String path = headers.firstValue(":path").orElse("");
+ System.out.println("path = " + path);
+ String scheme = headers.firstValue(":scheme").orElse("");
+ System.out.println("scheme = " + scheme);
+ String authority = headers.firstValue(":authority").orElse("");
+ System.out.println("authority = " + authority);
+ HttpHeadersImpl rspheaders = new HttpHeadersImpl();
+ int winsize = clientSettings.getParameter(
+ SettingsFrame.INITIAL_WINDOW_SIZE);
+ System.err.println ("Stream window size = " + winsize);
+ try (
+ BodyInputStream bis = new BodyInputStream(queue, streamid, this);
+ BodyOutputStream bos = new BodyOutputStream(streamid, winsize, this);
+ )
+ {
+ String us = scheme + "://" + authority + path;
+ URI uri = new URI(us);
+ boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1;
+ Http2TestExchange exchange = new Http2TestExchange(streamid, method,
+ headers, rspheaders, uri, bis, bos, this, pushAllowed);
+
+ // give to user
+ handler.handle(exchange);
+
+ // everything happens in the exchange from here. Hopefully will
+ // return though.
+ } catch (Throwable e) {
+ System.err.println("TestServer: handleRequest exception: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ // Runs in own thread
+
+ @SuppressWarnings({"rawtypes","unchecked"})
+ void readLoop() {
+ try {
+ while (!stopping) {
+ Http2Frame frame = readFrame();
+ int stream = frame.streamid();
+ if (stream == 0) {
+ if (frame.type() == WindowUpdateFrame.TYPE) {
+ WindowUpdateFrame wup = (WindowUpdateFrame) frame;
+ updateConnectionWindow(wup.getUpdate());
+ } else {
+ // other common frame types
+ handleCommonFrame(frame);
+ }
+ } else {
+ Queue q = streams.get(stream);
+ if (frame.type() == HeadersFrame.TYPE) {
+ if (q != null) {
+ System.err.println("HEADERS frame for existing stream! Error.");
+ // TODO: close connection
+ continue;
+ } else {
+ createStream((HeadersFrame) frame);
+ }
+ } else {
+ if (q == null) {
+ System.err.printf("Non Headers frame received with"+
+ " non existing stream (%d) ", frame.streamid());
+ System.err.println(frame);
+ continue;
+ }
+ if (frame.type() == WindowUpdateFrame.TYPE) {
+ WindowUpdateFrame wup = (WindowUpdateFrame) frame;
+ synchronized (updaters) {
+ Consumer<Integer> r = updaters.get(stream);
+ r.accept(wup.getUpdate());
+ }
+ } else {
+ q.put(frame);
+ }
+ }
+ }
+ }
+ } catch (Throwable e) {
+ close();
+ if (!stopping) {
+ System.err.println("Http server reader thread shutdown");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // set streamid outside plus other specific fields
+ void encodeHeaders(HttpHeadersImpl headers, HeaderFrame out) {
+ List<ByteBuffer> buffers = new LinkedList<>();
+
+ ByteBuffer buf = getBuffer();
+ boolean encoded;
+ for (Map.Entry<String, List<String>> entry : headers.map().entrySet()) {
+ List<String> values = entry.getValue();
+ String key = entry.getKey().toLowerCase();
+ for (String value : values) {
+ do {
+ hpackOut.header(key, value);
+ encoded = hpackOut.encode(buf);
+ if (!encoded) {
+ buf.flip();
+ buffers.add(buf);
+ buf = getBuffer();
+ }
+ } while (!encoded);
+ }
+ }
+ buf.flip();
+ buffers.add(buf);
+ out.setFlags(HeaderFrame.END_HEADERS);
+ out.setHeaderBlock(buffers.toArray(bbarray));
+ }
+
+ static void closeIgnore(Closeable c) {
+ try {
+ c.close();
+ } catch (IOException e) {}
+ }
+
+ // Runs in own thread
+ void writeLoop() {
+ try {
+ while (!stopping) {
+ Http2Frame frame = outputQ.take();
+ if (frame instanceof ResponseHeaders) {
+ ResponseHeaders rh = (ResponseHeaders)frame;
+ HeadersFrame hf = new HeadersFrame();
+ encodeHeaders(rh.headers, hf);
+ hf.streamid(rh.streamid());
+ writeFrame(hf);
+ } else if (frame instanceof OutgoingPushPromise) {
+ handlePush((OutgoingPushPromise)frame);
+ } else
+ writeFrame(frame);
+ }
+ System.err.println("Connection writer stopping");
+ } catch (Throwable e) {
+ e.printStackTrace();
+ /*close();
+ if (!stopping) {
+ e.printStackTrace();
+ System.err.println("TestServer: writeLoop exception: " + e);
+ }*/
+ }
+ }
+
+ private void handlePush(OutgoingPushPromise op) throws IOException {
+ PushPromiseFrame pp = new PushPromiseFrame();
+ encodeHeaders(op.headers, pp);
+ int promisedStreamid = nextPushStreamId;
+ nextPushStreamId += 2;
+ pp.streamid(op.parentStream);
+ pp.setPromisedStream(promisedStreamid);
+ writeFrame(pp);
+ final InputStream ii = op.is;
+ final BodyOutputStream oo = new BodyOutputStream(
+ promisedStreamid,
+ clientSettings.getParameter(
+ SettingsFrame.INITIAL_WINDOW_SIZE), this);
+ oo.goodToGo();
+ exec.submit(() -> {
+ try {
+ ResponseHeaders oh = getPushResponse(promisedStreamid);
+ outputQ.put(oh);
+ ii.transferTo(oo);
+ } catch (Throwable ex) {
+ System.err.printf("TestServer: pushing response error: %s\n",
+ ex.toString());
+ } finally {
+ closeIgnore(ii);
+ closeIgnore(oo);
+ }
+ });
+
+ }
+
+ // returns a minimal response with status 200
+ // that is the response to the push promise just sent
+ private ResponseHeaders getPushResponse(int streamid) {
+ HttpHeadersImpl h = new HttpHeadersImpl();
+ h.addHeader(":status", "200");
+ ResponseHeaders oh = new ResponseHeaders(h);
+ oh.streamid(streamid);
+ return oh;
+ }
+
+ private ByteBuffer getBuffer() {
+ return ByteBuffer.allocate(8 * 1024);
+ }
+
+ private Http2Frame readFrame() throws IOException {
+ byte[] buf = new byte[9];
+ if (is.readNBytes(buf, 0, 9) != 9)
+ throw new IOException("readFrame: connection closed");
+ int len = 0;
+ for (int i = 0; i < 3; i++) {
+ int n = buf[i] & 0xff;
+ //System.err.println("n = " + n);
+ len = (len << 8) + n;
+ }
+ byte[] rest = new byte[len];
+ int n = is.readNBytes(rest, 0, len);
+ if (n != len)
+ throw new IOException("Error reading frame");
+ ByteBufferConsumer bc = new ByteBufferConsumer(
+ new LinkedList<ByteBuffer>(List.of(ByteBuffer.wrap(buf), ByteBuffer.wrap(rest))),
+ this::getBuffer);
+ return Http2Frame.readIncoming(bc);
+ }
+
+ void sendSettingsFrame() throws IOException {
+ sendSettingsFrame(false);
+ }
+
+ void sendSettingsFrame(boolean now) throws IOException {
+ if (serverSettings == null) {
+ serverSettings = SettingsFrame.getDefaultSettings();
+ }
+ if (now) {
+ writeFrame(serverSettings);
+ } else {
+ outputQ.put(serverSettings);
+ }
+ }
+
+ String readUntil(String end) throws IOException {
+ int number = end.length();
+ int found = 0;
+ StringBuilder sb = new StringBuilder();
+ while (found < number) {
+ char expected = end.charAt(found);
+ int c = is.read();
+ if (c == -1) {
+ throw new IOException("Connection closed");
+ }
+ char c0 = (char) c;
+ sb.append(c0);
+ if (c0 != expected) {
+ found = 0;
+ continue;
+ }
+ found++;
+ }
+ return sb.toString();
+ }
+
+ private int getContentLength(String headers) {
+ return getIntHeader(headers, "Content-length");
+ }
+
+ private int getIntHeader(String headers, String name) {
+ String val = getHeader(headers, name);
+ if (val == null) {
+ return -1;
+ }
+ return Integer.parseInt(val);
+ }
+
+ private String getHeader(String headers, String name) {
+ String headers1 = headers.toLowerCase(); // not efficient
+ name = CRLF + name.toLowerCase();
+ int start = headers1.indexOf(name);
+ if (start == -1) {
+ return null;
+ }
+ start += 2;
+ int end = headers1.indexOf(CRLF, start);
+ String line = headers.substring(start, end);
+ start = line.indexOf(':');
+ if (start == -1) {
+ return null;
+ }
+ return line.substring(start + 1).trim();
+ }
+
+ final static String CRLF = "\r\n";
+
+ String readHttp1Request() throws IOException {
+ String headers = readUntil(CRLF + CRLF);
+ int clen = getContentLength(headers);
+ // read the content. There shouldn't be content but ..
+ byte[] buf = new byte[clen];
+ is.readNBytes(buf, 0, clen);
+ String body = new String(buf, "US-ASCII");
+ return headers + body;
+ }
+
+ void sendHttp1Response(int code, String msg, String... headers) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("HTTP/1.1 ")
+ .append(code)
+ .append(' ')
+ .append(msg)
+ .append(CRLF);
+ int numheaders = headers.length;
+ for (int i = 0; i < numheaders; i += 2) {
+ sb.append(headers[i])
+ .append(": ")
+ .append(headers[i + 1])
+ .append(CRLF);
+ }
+ sb.append(CRLF);
+ String s = sb.toString();
+ os.write(s.getBytes("US-ASCII"));
+ os.flush();
+ }
+
+ private void unexpectedFrame(Http2Frame frame) {
+ System.err.println("OOPS. Unexpected");
+ assert false;
+ }
+
+ final static ByteBuffer[] bbarray = new ByteBuffer[0];
+
+ // wrapper around a BlockingQueue that throws an exception when it's closed
+ // Each stream has one of these
+
+ String getRequestBody(String request) {
+ int bodystart = request.indexOf(CRLF+CRLF);
+ String body;
+ if (bodystart == -1)
+ body = "";
+ else
+ body = request.substring(bodystart+4);
+ return body;
+ }
+
+ @SuppressWarnings({"rawtypes","unchecked"})
+ void addRequestBodyToQueue(String body, Queue q) throws IOException {
+ ByteBuffer buf = ByteBuffer.wrap(body.getBytes(StandardCharsets.US_ASCII));
+ DataFrame df = new DataFrame();
+ df.streamid(1); // only used for primordial stream
+ df.setData(buf);
+ df.computeLength();
+ df.setFlag(DataFrame.END_STREAM);
+ q.put(df);
+ }
+
+ // window updates done in main reader thread because they may
+ // be used to unblock BodyOutputStreams waiting for WUPs
+
+ HashMap<Integer,Consumer<Integer>> updaters = new HashMap<>();
+
+ void registerStreamWindowUpdater(int streamid, Consumer<Integer> r) {
+ synchronized(updaters) {
+ updaters.put(streamid, r);
+ }
+ }
+
+ int sendWindow = 64 * 1024 - 1; // connection level send window
+
+ /**
+ * BodyOutputStreams call this to get the connection window first.
+ *
+ * @param amount
+ */
+ synchronized void obtainConnectionWindow(int amount) throws InterruptedException {
+ while (amount > 0) {
+ int n = Math.min(amount, sendWindow);
+ amount -= n;
+ sendWindow -= n;
+ if (amount > 0)
+ wait();
+ }
+ }
+
+ synchronized void updateConnectionWindow(int amount) {
+ sendWindow += amount;
+ notifyAll();
+ }
+
+ // simplified output headers class. really just a type safe container
+ // for the hashmap.
+
+ static class ResponseHeaders extends Http2Frame {
+ HttpHeadersImpl headers;
+
+ ResponseHeaders(HttpHeadersImpl headers) {
+ this.headers = headers;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ throw new UnsupportedOperationException("Not supported ever!");
+ }
+
+ @Override
+ void computeLength() {
+ throw new UnsupportedOperationException("Not supported ever!");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/OutgoingPushPromise.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,31 @@
+package java.net.http;
+
+import java.io.*;
+import java.net.*;
+
+// will be converted to a PushPromiseFrame in the writeLoop
+// a thread is then created to produce the DataFrames from the InputStream
+class OutgoingPushPromise extends Http2Frame {
+ final HttpHeadersImpl headers;
+ final URI uri;
+ final InputStream is;
+ final int parentStream; // not the pushed streamid
+
+ OutgoingPushPromise(int parentStream, URI uri, HttpHeadersImpl headers, InputStream is) {
+ this.uri = uri;
+ this.headers = headers;
+ this.is = is;
+ this.parentStream = parentStream;
+ }
+
+ @Override
+ void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ void computeLength() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/PushHandler.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,71 @@
+/*
+ * 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
+ * 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 java.net.http;
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.http.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class PushHandler implements Http2Handler {
+
+ final Path tempFile;
+ final int loops;
+
+ public PushHandler(int file_size, int loops) throws Exception {
+ tempFile = TestUtil.getAFile(file_size);
+ this.loops = loops;
+ }
+
+ int invocation = 0;
+
+ public void handle(Http2TestExchange ee) {
+ try {
+ System.err.println ("Server: handle " + ee);
+ invocation++;
+
+ if (ee.serverPushAllowed()) {
+ for (int i=0; i<loops; i++) {
+ InputStream is = new FileInputStream(tempFile.toFile());
+ URI u = new URI ("http://www.foo.com/" + Integer.toString(i));
+ HttpHeadersImpl h = new HttpHeadersImpl();
+ h.addHeader("X-foo", "bar");
+ ee.serverPush(u, h, is);
+ }
+ System.err.println ("Server: sent all pushes");
+ }
+ ee.sendResponseHeaders(200, 0);
+ OutputStream os = ee.getResponseBody();
+ InputStream iis = new FileInputStream(tempFile.toFile());
+ iis.transferTo(os);
+ os.close();
+ iis.close();
+ } catch (Exception ex) {
+ System.err.println ("Server: exception " + ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/TestUtil.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,81 @@
+/*
+ * 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
+ * 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 java.net.http;
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.concurrent.*;
+import java.util.Arrays;
+
+public class TestUtil {
+
+ final static String fileContent = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // repeated
+
+ public static Path getAFile(int size) throws IOException {
+ Path p = tempFile();
+ BufferedWriter writer = Files.newBufferedWriter(p);
+ int len = fileContent.length();
+ int iterations = size / len;
+ int remainder = size - (iterations * len);
+ for (int i=0; i<iterations; i++)
+ writer.write(fileContent, 0, len);
+ writer.write(fileContent, 0, remainder);
+ writer.close();
+ return p;
+ }
+
+ public static Path tempFile() {
+ try {
+ Path p = Files.createTempFile("foo", "test");
+ p.toFile().deleteOnExit();
+ return p;
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ public static Void compareFiles(Path path1, Path path2) {
+ try {
+ if (Files.size(path1) != Files.size(path2))
+ throw new RuntimeException("File sizes do not match");
+ compareContents(path1, path2);
+ return null;
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ static void compareContents(Path path1, Path path2) {
+ try {
+ byte[] b1 = Files.readAllBytes(path1);
+ byte[] b2 = Files.readAllBytes(path2);
+ if (!Arrays.equals(b1, b2))
+ throw new RuntimeException ("Files do not match");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+}
--- a/jdk/test/java/net/httpclient/security/0.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/0.policy Fri May 06 06:23:30 2016 -0700
@@ -2,8 +2,7 @@
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/1.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/1.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 1
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
@@ -13,7 +12,7 @@
// permissions specific to this test
- permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET";
+ permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET";
};
// For proxy only. Not being tested
--- a/jdk/test/java/net/httpclient/security/10.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/10.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 10
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
@@ -12,7 +11,7 @@
permission java.lang.RuntimePermission "createClassLoader";
// permissions specific to this test
- permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*";
+ permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET:*";
};
// For proxy only. Not being tested
--- a/jdk/test/java/net/httpclient/security/11.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/11.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 11
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
@@ -12,8 +11,8 @@
permission java.lang.RuntimePermission "createClassLoader";
// permissions specific to this test
- permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*";
- permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT";
+ permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET:*";
+ permission java.net.URLPermission "socket://127.0.0.1:${port.number1}", "CONNECT";
};
--- a/jdk/test/java/net/httpclient/security/12.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/12.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 11
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
@@ -12,8 +11,8 @@
permission java.lang.RuntimePermission "createClassLoader";
// permissions specific to this test
- permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*";
- permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT";
+ permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET:*";
+ permission java.net.URLPermission "socket://127.0.0.1:${port.number1}", "CONNECT";
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/security/14.policy Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,23 @@
+// Policy 14
+grant {
+ // permissions common to all tests
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
+ permission java.net.NetPermission "getDefaultHttpClient";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.logging.LoggingPermission "control", "";
+ permission java.net.SocketPermission "localhost:1024-", "accept,listen";
+ permission java.io.FilePermission "${test.src}${/}docs${/}-", "read";
+ permission java.lang.RuntimePermission "createClassLoader";
+
+
+ // permissions specific to this test
+ permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET";
+};
+
+// For proxy only. Not being tested
+grant codebase "file:${test.classes}/proxydir/-" {
+ permission java.net.SocketPermission "localhost:1024-", "accept,listen,connect";
+ permission java.net.SocketPermission "127.0.0.1:1024-", "connect,resolve";
+};
+
--- a/jdk/test/java/net/httpclient/security/15.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/15.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 11
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
@@ -13,10 +12,9 @@
// permissions specific to this test
permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*";
- permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT";
// Test checks for this explicitly
- permission java.net.RuntimePermission "foobar";
+ permission java.net.RuntimePermission "foobar";
};
--- a/jdk/test/java/net/httpclient/security/2.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/2.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 2
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/3.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/3.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 3
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/4.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/4.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 4
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/5.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/5.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 5
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/6.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/6.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 6
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/7.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/7.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 7
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/8.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/8.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 8
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- a/jdk/test/java/net/httpclient/security/9.policy Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/9.policy Fri May 06 06:23:30 2016 -0700
@@ -1,8 +1,7 @@
// Policy 9
grant {
// permissions common to all tests
- permission java.util.PropertyPermission "test.src", "read";
- permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete";
permission java.net.NetPermission "getDefaultHttpClient";
permission java.lang.RuntimePermission "modifyThread";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/security/Driver.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,139 @@
+/*
+ * 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
+ * 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 8087112
+ * @library /lib/testlibrary/
+ * @build jdk.testlibrary.SimpleSSLContext jdk.testlibrary.Utils
+ * @compile ../../../../com/sun/net/httpserver/LogFilter.java
+ * @compile ../../../../com/sun/net/httpserver/FileServerHandler.java
+ * @compile ../ProxyServer.java
+ * @build Security
+ *
+ * @run driver/timeout=60 Driver
+ */
+
+/**
+ * driver required for allocating free portnumbers and putting this number
+ * into security policy file used in some tests.
+ *
+ * The tests are in Security.java and port number supplied in -Dport.number
+ * and -Dport.number1 for tests that require a second free port
+ */
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.io.*;
+import java.net.*;
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.Utils;
+
+/**
+ * Driver for tests
+ */
+public class Driver {
+
+ public static void main(String[] args) throws Throwable {
+ System.out.println("Starting Driver");
+ runtest("1.policy", "1");
+ runtest("10.policy", "10");
+ runtest("11.policy", "11");
+ runtest("12.policy", "12");
+ System.out.println("DONE");
+ }
+
+ static class Logger extends Thread {
+ private final OutputStream ps;
+ private final InputStream stdout;
+
+ Logger(String cmdLine, Process p, String dir) throws IOException {
+ super();
+ setDaemon(true);
+ cmdLine = "Command line = [" + cmdLine + "]";
+ stdout = p.getInputStream();
+ File f = File.createTempFile("debug", ".txt", new File(dir));
+ ps = new FileOutputStream(f);
+ ps.write(cmdLine.getBytes());
+ ps.flush();
+ }
+
+ public void run() {
+ try {
+ byte[] buf = new byte[128];
+ int c;
+ while ((c = stdout.read(buf)) != -1) {
+ ps.write(buf, 0, c);
+ ps.flush();
+ }
+ ps.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void runtest(String policy, String testnum) throws Throwable {
+
+ String testJdk = System.getProperty("test.jdk", "?");
+ String testSrc = System.getProperty("test.src", "?");
+ String testClassPath = System.getProperty("test.class.path", "?");
+ String testClasses = System.getProperty("test.classes", "?");
+ String sep = System.getProperty("file.separator", "?");
+ String javaCmd = testJdk + sep + "bin" + sep + "java";
+ int retval = 10; // 10 is special exit code denoting a bind error
+ // in which case, we retry
+ while (retval == 10) {
+ List<String> cmd = new ArrayList<>();
+ cmd.add(javaCmd);
+ cmd.add("-Dtest.jdk=" + testJdk);
+ cmd.add("-Dtest.src=" + testSrc);
+ cmd.add("-Dtest.classes=" + testClasses);
+ cmd.add("-Djava.security.manager");
+ cmd.add("-Djava.security.policy=" + testSrc + sep + policy);
+ cmd.add("-Dport.number=" + Integer.toString(Utils.getFreePort()));
+ cmd.add("-Dport.number1=" + Integer.toString(Utils.getFreePort()));
+ cmd.add("-cp");
+ cmd.add(testClassPath);
+ cmd.add("Security");
+ cmd.add(testnum);
+
+ ProcessBuilder processBuilder = new ProcessBuilder(cmd)
+ .redirectOutput(ProcessBuilder.Redirect.PIPE)
+ .redirectErrorStream(true);
+
+ String cmdLine = cmd.stream().collect(Collectors.joining(" "));
+ Process child = processBuilder.start();
+ Logger log = new Logger(cmdLine, child, testClasses);
+ log.start();
+ retval = child.waitFor();
+ System.out.println("retval = " + retval);
+ }
+ if (retval != 0) {
+ Thread.sleep(2000);
+ throw new RuntimeException("Non zero return value");
+ }
+ }
+}
--- a/jdk/test/java/net/httpclient/security/Security.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/net/httpclient/security/Security.java Fri May 06 06:23:30 2016 -0700
@@ -32,7 +32,6 @@
* @compile ../ProxyServer.java
*
* @run main/othervm/secure=java.lang.SecurityManager/policy=0.policy Security 0
- * @run main/othervm/secure=java.lang.SecurityManager/policy=1.policy Security 1
* @run main/othervm/secure=java.lang.SecurityManager/policy=2.policy Security 2
* @run main/othervm/secure=java.lang.SecurityManager/policy=3.policy Security 3
* @run main/othervm/secure=java.lang.SecurityManager/policy=4.policy Security 4
@@ -41,14 +40,13 @@
* @run main/othervm/secure=java.lang.SecurityManager/policy=7.policy Security 7
* @run main/othervm/secure=java.lang.SecurityManager/policy=8.policy Security 8
* @run main/othervm/secure=java.lang.SecurityManager/policy=9.policy Security 9
- * @run main/othervm/secure=java.lang.SecurityManager/policy=10.policy Security 10
- * @run main/othervm/secure=java.lang.SecurityManager/policy=11.policy Security 11
- * @run main/othervm/secure=java.lang.SecurityManager/policy=12.policy Security 12
* @run main/othervm/secure=java.lang.SecurityManager/policy=0.policy Security 13
- * @run main/othervm/secure=java.lang.SecurityManager/policy=1.policy Security 14
+ * @run main/othervm/secure=java.lang.SecurityManager/policy=14.policy Security 14
* @run main/othervm/secure=java.lang.SecurityManager/policy=15.policy Security 15
*/
+// Tests 1, 10, 11 and 12 executed from Driver
+
import com.sun.net.httpserver.*;
import java.io.IOException;
import java.io.InputStream;
@@ -78,7 +76,7 @@
static HttpServer s1 = null;
static ExecutorService executor=null;
- static int port;
+ static int port, proxyPort;
static HttpClient client;
static String httproot, fileuri, fileroot, redirectroot;
static List<HttpClient> clients = new LinkedList<>();
@@ -136,6 +134,9 @@
if (!dest.toFile().exists()) {
System.out.printf("moving %s to %s\n", src.toString(), dest.toString());
Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING);
+ } else if (src.toFile().exists()) {
+ System.out.printf("%s exists, deleting %s\n", dest.toString(), src.toString());
+ Files.delete(src);
} else {
System.out.printf("NOT moving %s to %s\n", src.toString(), dest.toString());
}
@@ -225,15 +226,15 @@
}),
// (10) policy has permission for destination URL but not for proxy
test(false, () -> { //Policy 10
- directProxyTest(27208, true);
+ directProxyTest(proxyPort, true);
}),
// (11) policy has permission for both destination URL and proxy
test(true, () -> { //Policy 11
- directProxyTest(27301, true);
+ directProxyTest(proxyPort, true);
}),
// (12) policy has permission for both destination URL and proxy
test(false, () -> { //Policy 11
- directProxyTest(28301, false);
+ directProxyTest(proxyPort, false);
}),
// (13) async version of test 0
test(false, () -> { // Policy 0
@@ -350,6 +351,8 @@
throw new RuntimeException("Failed");
}
System.out.println (policy + " succeeded as expected");
+ } catch (BindException e) {
+ System.exit(10);
} catch (SecurityException e) {
if (succeeds) {
System.out.println("FAILED");
@@ -362,8 +365,12 @@
}
public static void main(String[] args) throws Exception {
- initServer();
- setupProxy();
+ try {
+ initServer();
+ setupProxy();
+ } catch (BindException e) {
+ System.exit(10);
+ }
fileroot = System.getProperty ("test.src")+ "/docs";
int testnum = Integer.parseInt(args[0]);
String policy = args[0];
@@ -382,33 +389,25 @@
runtest(tr.test, policy, tr.result);
} finally {
s1.stop(0);
- //executor.shutdownNow();
+ executor.shutdownNow();
for (HttpClient client : clients)
client.executorService().shutdownNow();
}
}
- // create Http Server on port range below. So, we can
- HttpServer createServer() {
- HttpServer server;
- for (int i=25800; i<26800; i++) {
- InetSocketAddress a = new InetSocketAddress(i);
- try {
- server = HttpServer.create(a, 0);
- return server;
- } catch (IOException e) {}
- }
- return null;
- }
+ public static void initServer() throws Exception {
+ String portstring = System.getProperty("port.number");
+ port = portstring != null ? Integer.parseInt(portstring) : 0;
+ portstring = System.getProperty("port.number1");
+ proxyPort = portstring != null ? Integer.parseInt(portstring) : 0;
- public static void initServer() throws Exception {
Logger logger = Logger.getLogger("com.sun.net.httpserver");
ConsoleHandler ch = new ConsoleHandler();
logger.setLevel(Level.ALL);
ch.setLevel(Level.ALL);
logger.addHandler(ch);
String root = System.getProperty ("test.src")+ "/docs";
- InetSocketAddress addr = new InetSocketAddress (0);
+ InetSocketAddress addr = new InetSocketAddress (port);
s1 = HttpServer.create (addr, 0);
if (s1 instanceof HttpsServer) {
throw new RuntimeException ("should not be httpsserver");
@@ -423,7 +422,13 @@
s1.setExecutor (executor);
s1.start();
- port = s1.getAddress().getPort();
+ if (port == 0)
+ port = s1.getAddress().getPort();
+ else {
+ if (s1.getAddress().getPort() != port)
+ throw new RuntimeException("Error wrong port");
+ System.out.println("Port was assigned by Driver");
+ }
System.out.println("HTTP server port = " + port);
httproot = "http://127.0.0.1:" + port + "/files/";
redirectroot = "http://127.0.0.1:" + port + "/redirect/";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/WatchService/DeleteInterference.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016, Red Hat, Inc. and/or its affiliates.
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8153925
+ * @summary Tests potential interference between a thread creating and closing
+ * a WatchService with another thread that is deleting and re-creating the
+ * directory at around the same time. This scenario tickled a timing bug
+ * in the Windows implementation.
+ */
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.WatchService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import static java.nio.file.StandardWatchEventKinds.*;
+
+public class DeleteInterference {
+
+ private static final int ITERATIONS_COUNT = 1024;
+
+ /**
+ * Execute two tasks in a thread pool. One task loops on creating and
+ * closing a WatchService, the other task deletes and re-creates the
+ * directory.
+ */
+ public static void main(String[] args) throws Exception {
+ Path dir = Files.createTempDirectory("work");
+ ExecutorService pool = Executors.newCachedThreadPool();
+ try {
+ Future<?> task1 = pool.submit(() -> openAndCloseWatcher(dir));
+ Future<?> task2 = pool.submit(() -> deleteAndRecreateDirectory(dir));
+ task1.get();
+ task2.get();
+ } finally {
+ pool.shutdown();
+ deleteFileTree(dir);
+ }
+ }
+
+ private static void openAndCloseWatcher(Path dir) {
+ FileSystem fs = FileSystems.getDefault();
+ for (int i = 0; i < ITERATIONS_COUNT; i++) {
+ try (WatchService watcher = fs.newWatchService()) {
+ dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+
+ private static void deleteAndRecreateDirectory(Path dir) {
+ for (int i = 0; i < ITERATIONS_COUNT; i++) {
+ try {
+ deleteFileTree(dir);
+ Path subdir = Files.createDirectories(dir.resolve("subdir"));
+ Files.createFile(subdir.resolve("test"));
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+
+ private static void deleteFileTree(Path file) {
+ try {
+ if (Files.isDirectory(file)) {
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(file)) {
+ for (Path pa : stream) {
+ deleteFileTree(pa);
+ }
+ }
+ }
+ Files.delete(file);
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Arrays/AsList.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,93 @@
+/*
+ * 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 8155600
+ * @summary Tests for Arrays.asList()
+ * @run testng AsList
+ */
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.stream.IntStream;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+public class AsList {
+ /*
+ * Iterator contract test
+ */
+ @Test(dataProvider = "Arrays")
+ public void testIterator(Object[] array) {
+ Iterator<Object> itr = Arrays.asList(array).iterator();
+ for (int i = 0; i < array.length; i++) {
+ assertTrue(itr.hasNext());
+ assertTrue(itr.hasNext()); // must be idempotent
+ assertSame(array[i], itr.next());
+ try {
+ itr.remove();
+ fail("Remove must throw");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+ }
+ assertFalse(itr.hasNext());
+ for (int i = 0; i < 3; i++) {
+ assertFalse(itr.hasNext());
+ try {
+ itr.next();
+ fail("Next succeed when there's no data left");
+ } catch (NoSuchElementException ex) {
+ // expected
+ }
+ }
+ }
+
+ @DataProvider(name = "Arrays")
+ public static Object[][] arrays() {
+ Object[][] arrays = {
+ { new Object[] { } },
+ { new Object[] { 1 } },
+ { new Object[] { null } },
+ { new Object[] { null, 1 } },
+ { new Object[] { 1, null } },
+ { new Object[] { null, null } },
+ { new Object[] { null, 1, 2 } },
+ { new Object[] { 1, null, 2 } },
+ { new Object[] { 1, 2, null } },
+ { new Object[] { null, null, null } },
+ { new Object[] { 1, 2, 3, null, 4 } },
+ { new Object[] { "a", "a", "a", "a" } },
+ { IntStream.range(0, 100).boxed().toArray() }
+ };
+
+ return arrays;
+ }
+}
--- a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh Fri May 06 06:23:30 2016 -0700
@@ -68,7 +68,7 @@
${TESTJAVA}/bin/jar xf ${TESTSRC}/awtres.jar
echo
-${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:${PATCHDIR} \
+${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:java.desktop=${PATCHDIR}/java.desktop \
-cp ${TESTCLASSES} Bug6299235Test
if [ $? -ne 0 ]
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java Fri May 06 06:23:30 2016 -0700
@@ -26,7 +26,7 @@
* @bug 8132734
* @summary Test the System properties for JarFile that support multi-release jar files
* @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer
* @run testng MultiReleaseJarHttpProperties
* @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties
* @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties
@@ -43,8 +43,6 @@
* @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
*/
-import com.sun.net.httpserver.*;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -73,7 +71,7 @@
@Override
protected void initializeClassLoader() throws Exception {
URL[] urls = new URL[]{
- new URL("http://localhost:" + server.getPort() + "/multi-release-jar")
+ new URL("http://localhost:" + server.getPort() + "/multi-release.jar")
};
cldr = new URLClassLoader(urls);
// load any class, Main is convenient and in the root entries
@@ -112,45 +110,3 @@
getResource(rootClass, resource);
}
}
-
-/**
- * Extremely simple server that only performs one task. The server listens for
- * requests on the ephemeral port. If it sees a request that begins with
- * "/multi-release-jar", it consumes the request and returns a stream of bytes
- * representing the jar file multi-release.jar found in "userdir".
- */
-class SimpleHttpServer {
- private static final String userdir = System.getProperty("user.dir", ".");
- private static final Path multirelease = Paths.get(userdir, "multi-release.jar");
-
- private final HttpServer server;
-
- public SimpleHttpServer() throws IOException {
- server = HttpServer.create();
- }
-
- public void start() throws IOException {
- server.bind(new InetSocketAddress(0), 0);
- server.createContext("/multi-release-jar", t -> {
- try (InputStream is = t.getRequestBody()) {
- is.readAllBytes(); // probably not necessary to consume request
- byte[] bytes = Files.readAllBytes(multirelease);
- t.sendResponseHeaders(200, bytes.length);
- try (OutputStream os = t.getResponseBody()) {
- os.write(bytes);
- }
- }
- });
- server.setExecutor(null); // creates a default executor
- server.start();
- }
-
- public void stop() {
- server.stop(0);
- }
-
- int getPort() {
- return server.getAddress().getPort();
- }
-}
-
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java Fri May 06 06:23:30 2016 -0700
@@ -27,11 +27,18 @@
import java.util.Arrays;
import java.util.Random;
+import java.util.Spliterator;
import java.util.stream.DoubleStream;
import java.util.stream.LongStream;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+/**
+ * @test
+ * @bug 8153293
+ */
@Test
public class DoublePrimitiveOpsTests {
@@ -42,6 +49,13 @@
assertEquals(sum, 1.0 + 2.0 + 3.0 + 4.0 + 5.0);
}
+ public void testFlags() {
+ assertTrue(LongStream.range(1, 10).asDoubleStream().boxed().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ assertFalse(DoubleStream.of(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ }
+
public void testToArray() {
{
double[] array = LongStream.range(1, 10).asDoubleStream().map(i -> i * 2).toArray();
@@ -72,6 +86,22 @@
}
}
+ public void testSortDistinct() {
+ {
+ double[] range = LongStream.range(0, 10).asDoubleStream().toArray();
+
+ assertEquals(LongStream.range(0, 10).asDoubleStream().sorted().distinct().toArray(), range);
+ assertEquals(LongStream.range(0, 10).asDoubleStream().parallel().sorted().distinct().toArray(), range);
+
+ double[] data = {5, 3, 1, 1, 5, Double.NaN, 3, 9, Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY, 2, 9, 1, 0, 8, Double.NaN, -0.0};
+ double[] expected = {Double.NEGATIVE_INFINITY, -0.0, 0, 1, 2, 3, 5, 8, 9,
+ Double.POSITIVE_INFINITY, Double.NaN};
+ assertEquals(DoubleStream.of(data).sorted().distinct().toArray(), expected);
+ assertEquals(DoubleStream.of(data).parallel().sorted().distinct().toArray(), expected);
+ }
+ }
+
public void testSortSort() {
Random r = new Random();
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java Fri May 06 06:23:30 2016 -0700
@@ -28,13 +28,21 @@
import java.util.Arrays;
import java.util.List;
import java.util.Random;
+import java.util.Spliterator;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntConsumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+/**
+ * @test
+ * @bug 8153293
+ */
@Test
public class IntPrimitiveOpsTests {
@@ -85,6 +93,29 @@
assertEquals(sum, 15);
}
+ public void testFlags() {
+ assertTrue(IntStream.range(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+ assertFalse(IntStream.of(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ assertFalse(IntStream.of(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.DISTINCT));
+
+ assertTrue(IntStream.range(1, 10).asLongStream().spliterator()
+ .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+ assertFalse(IntStream.of(1, 10).asLongStream().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ assertFalse(IntStream.of(1, 10).asLongStream().spliterator()
+ .hasCharacteristics(Spliterator.DISTINCT));
+
+ assertTrue(IntStream.range(1, 10).asDoubleStream().spliterator()
+ .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+ assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator()
+ .hasCharacteristics(Spliterator.DISTINCT));
+ }
+
public void testToArray() {
{
int[] array = IntStream.range(1, 10).map(i -> i * 2).toArray();
@@ -115,6 +146,35 @@
}
}
+ public void testSortDistinct() {
+ {
+ int[] range = IntStream.range(0, 10).toArray();
+
+ assertEquals(IntStream.range(0, 10).sorted().distinct().toArray(), range);
+ assertEquals(IntStream.range(0, 10).parallel().sorted().distinct().toArray(), range);
+
+ int[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8};
+ int[] expected = {0, 1, 2, 3, 5, 8, 9};
+ assertEquals(IntStream.of(data).sorted().distinct().toArray(), expected);
+ assertEquals(IntStream.of(data).parallel().sorted().distinct().toArray(), expected);
+ }
+
+ {
+ int[] input = new Random().ints(100, -10, 10).map(x -> x+Integer.MAX_VALUE).toArray();
+ TreeSet<Long> longs = new TreeSet<>();
+ for(int i : input) longs.add((long)i);
+ long[] expectedLongs = longs.stream().mapToLong(Long::longValue).toArray();
+ assertEquals(IntStream.of(input).sorted().asLongStream().sorted().distinct().toArray(),
+ expectedLongs);
+
+ TreeSet<Double> doubles = new TreeSet<>();
+ for(int i : input) doubles.add((double)i);
+ double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray();
+ assertEquals(IntStream.of(input).sorted().distinct().asDoubleStream()
+ .sorted().distinct().toArray(), expectedDoubles);
+ }
+ }
+
public void testSortSort() {
Random r = new Random();
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java Fri May 06 06:23:30 2016 -0700
@@ -28,13 +28,21 @@
import java.util.Arrays;
import java.util.List;
import java.util.Random;
+import java.util.Spliterator;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.LongConsumer;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+/**
+ * @test
+ * @bug 8153293
+ */
@Test
public class LongPrimitiveOpsTests {
@@ -85,6 +93,22 @@
assertEquals(sum, 15);
}
+ public void testFlags() {
+ assertTrue(LongStream.range(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+ assertFalse(LongStream.of(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ assertFalse(LongStream.of(1, 10).boxed().spliterator()
+ .hasCharacteristics(Spliterator.DISTINCT));
+
+ assertTrue(LongStream.range(1, 10).asDoubleStream().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ assertFalse(LongStream.range(1, 10).asDoubleStream().spliterator()
+ .hasCharacteristics(Spliterator.DISTINCT));
+ assertFalse(LongStream.of(1, 10).asDoubleStream().spliterator()
+ .hasCharacteristics(Spliterator.SORTED));
+ }
+
public void testToArray() {
{
long[] array = LongStream.range(1, 10).map(i -> i * 2).toArray();
@@ -115,6 +139,30 @@
}
}
+ public void testSortDistinct() {
+ {
+ long[] range = LongStream.range(0, 10).toArray();
+
+ assertEquals(LongStream.range(0, 10).sorted().distinct().toArray(), range);
+ assertEquals(LongStream.range(0, 10).parallel().sorted().distinct().toArray(), range);
+
+ long[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8};
+ long[] expected = {0, 1, 2, 3, 5, 8, 9};
+ assertEquals(LongStream.of(data).sorted().distinct().toArray(), expected);
+ assertEquals(LongStream.of(data).parallel().sorted().distinct().toArray(), expected);
+ }
+
+ {
+ long[] input = new Random().longs(100, -10, 10).map(x -> x+Long.MAX_VALUE).toArray();
+
+ TreeSet<Double> doubles = new TreeSet<>();
+ for(long i : input) doubles.add((double)i);
+ double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray();
+ assertEquals(LongStream.of(input).sorted().distinct().asDoubleStream()
+ .sorted().distinct().toArray(), expectedDoubles);
+ }
+ }
+
public void testSortSort() {
Random r = new Random();
--- a/jdk/test/javax/crypto/Cipher/CipherStreamClose.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/crypto/Cipher/CipherStreamClose.java Fri May 06 06:23:30 2016 -0700
@@ -27,6 +27,8 @@
* @summary Make sure Cipher IO streams doesn't call extra doFinal if close()
* is called multiple times. Additionally, verify the input and output streams
* match with encryption and decryption with non-stream crypto.
+ * @compile -addmods java.xml.bind CipherStreamClose.java
+ * @run main/othervm -addmods java.xml.bind CipherStreamClose
*/
import java.io.*;
--- a/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java Fri May 06 06:23:30 2016 -0700
@@ -27,8 +27,10 @@
* @summary test RMI-IIOP call with ConcurrentHashMap as an argument
* @library /lib/testlibrary
* @build jdk.testlibrary.*
- * @build Test HelloInterface HelloServer HelloClient HelloImpl _HelloImpl_Tie _HelloInterface_Stub ConcurrentHashMapTest
- * @run main/othervm -Djava.naming.provider.url=iiop://localhost:1050 -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory ConcurrentHashMapTest
+ * @compile -addmods java.corba Test.java HelloInterface.java HelloServer.java HelloClient.java
+ * HelloImpl.java _HelloImpl_Tie.java _HelloInterface_Stub.java ConcurrentHashMapTest.java
+ * @run main/othervm -addmods java.corba -Djava.naming.provider.url=iiop://localhost:1050
+ * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory ConcurrentHashMapTest
* @key intermittent
*/
@@ -101,6 +103,8 @@
// -Djava.naming.provider.url=iiop://localhost:1050 HelloServer
List<String> commands = new ArrayList<>();
commands.add(ConcurrentHashMapTest.JAVA);
+ commands.add("-addmods");
+ commands.add("java.corba");
commands.add("-Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory");
commands.add("-Djava.naming.provider.url=iiop://localhost:1050");
commands.add("-cp");
--- a/jdk/test/javax/smartcardio/CommandAPDUTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/CommandAPDUTest.java Fri May 06 06:23:30 2016 -0700
@@ -26,7 +26,8 @@
* @bug 8049021
* @summary Test different constructors for CommandAPDU and check CLA,INS,NC,NE,
* P1,and P2
- * @run testng CommandAPDUTest
+ * @compile -addmods java.smartcardio CommandAPDUTest.java
+ * @run testng/othervm -addmods java.smartcardio CommandAPDUTest
*/
import java.nio.ByteBuffer;
import javax.smartcardio.CommandAPDU;
--- a/jdk/test/javax/smartcardio/HistoricalBytes.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/HistoricalBytes.java Fri May 06 06:23:30 2016 -0700
@@ -26,7 +26,9 @@
* @bug 6445367
* @summary Verify that ATR.getHistoricalBytes() works
* @author Andreas Sterbenz
-**/
+ * @compile -addmods java.smartcardio HistoricalBytes.java
+ * @run main/othervm -addmods java.smartcardio HistoricalBytes
+ */
import java.util.Arrays;
--- a/jdk/test/javax/smartcardio/ResponseAPDUTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/ResponseAPDUTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,8 @@
* @test
* @bug 8049021
* @summary Construct ResponseAPDU from byte array and check NR< SW, SW1 and SW2
- * @run testng ResponseAPDUTest
+ * @compile -addmods java.smartcardio ResponseAPDUTest.java
+ * @run testng/othervm -addmods java.smartcardio ResponseAPDUTest
*/
import javax.smartcardio.ResponseAPDU;
import static org.testng.Assert.*;
--- a/jdk/test/javax/smartcardio/Serialize.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/Serialize.java Fri May 06 06:23:30 2016 -0700
@@ -26,6 +26,8 @@
* @bug 6445367
* @summary make sure serialization works
* @author Andreas Sterbenz
+ * @compile -addmods java.smartcardio Serialize.java
+ * @run main/othervm -addmods java.smartcardio Serialize
*/
import java.io.*;
--- a/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,8 @@
* @test
* @bug 8049021
* @summary Test if we can write new provider for smart card
- * @run main/othervm/policy=policy TerminalFactorySpiTest
+ * @compile -addmods java.smartcardio TerminalFactorySpiTest.java
+ * @run main/othervm/policy=policy -addmods java.smartcardio TerminalFactorySpiTest
*/
import java.security.Provider;
import java.security.Security;
--- a/jdk/test/javax/smartcardio/TestCardPermission.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/TestCardPermission.java Fri May 06 06:23:30 2016 -0700
@@ -26,6 +26,8 @@
* @bug 6293767
* @summary Test for the CardPermission class
* @author Andreas Sterbenz
+ * @compile -addmods java.smartcardio TestCardPermission.java
+ * @run main/othervm -addmods java.smartcardio TestCardPermission
*/
import javax.smartcardio.*;
--- a/jdk/test/javax/smartcardio/TestCommandAPDU.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/smartcardio/TestCommandAPDU.java Fri May 06 06:23:30 2016 -0700
@@ -27,6 +27,8 @@
* @summary Test for the CommandAPDU class
* @author Andreas Sterbenz
* @key randomness
+ * @compile -addmods java.smartcardio TestCommandAPDU.java
+ * @run main/othervm -addmods java.smartcardio TestCommandAPDU
*/
import java.util.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/ClientProperty/UIClientPropertyKeyTest/UIClientPropertyKeyTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,113 @@
+/*
+ * 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.awt.EventQueue;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.UIClientPropertyKey;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+import static javax.swing.UIManager.getInstalledLookAndFeels;
+
+/**
+ * @test
+ * @bug 8141544
+ */
+public final class UIClientPropertyKeyTest {
+
+ private static Object key = new UIClientPropertyKey() {
+ };
+
+ public static void main(final String[] args) throws Exception {
+ EventQueue.invokeAndWait(UIClientPropertyKeyTest::testSetUI);
+ EventQueue.invokeAndWait(UIClientPropertyKeyTest::testSerialization);
+ }
+
+ /**
+ * UIClientPropertyKey should be removed after deserialization.
+ */
+ private static void testSerialization() {
+ JComponent comp = new JButton();
+ comp.putClientProperty("key1", "value1");
+ comp.putClientProperty(key, "value2");
+
+ comp = serializeDeserialize(comp);
+
+ validate(comp);
+ }
+
+ /**
+ * UIClientPropertyKey should be removed on updateUI().
+ */
+ private static void testSetUI() {
+ JComponent comp = new JButton();
+ comp.putClientProperty("key1", "value1");
+ for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) {
+ comp.putClientProperty(key, "value2");
+ setLookAndFeel(laf);
+ SwingUtilities.updateComponentTreeUI(comp);
+ validate(comp);
+ }
+ }
+
+ private static void validate(JComponent comp) {
+ Object value = comp.getClientProperty("key1");
+ if (!value.equals("value1")) {
+ throw new RuntimeException("Incorrect value: " + value);
+ }
+ value = comp.getClientProperty(key);
+ if (value != null) {
+ throw new RuntimeException("Incorrect value: " + value);
+ }
+ }
+
+ private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) {
+ try {
+ UIManager.setLookAndFeel(laf.getClassName());
+ System.out.println("LookAndFeel: " + laf.getClassName());
+ } catch (ClassNotFoundException | InstantiationException |
+ UnsupportedLookAndFeelException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static JComponent serializeDeserialize(JComponent comp) {
+ try {
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(byteOut);
+ out.writeObject(comp);
+ out.close();
+ return (JComponent) new ObjectInputStream(new ByteArrayInputStream(
+ byteOut.toByteArray())).readObject();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JButton/PressedButtonRightClickTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,112 @@
+/*
+ * 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.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8049069
+ * @summary Tests whether right mouse click releases a pressed JButton
+ */
+
+public class PressedButtonRightClickTest {
+
+ private static Robot testRobot;
+ private static JFrame myFrame;
+ private static JButton myButton;
+
+ public static void main(String[] args) throws Throwable {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ constructTestUI();
+ }
+ });
+
+ try {
+ testRobot = new Robot();
+ } catch (AWTException ex) {
+ throw new RuntimeException("Exception in Robot creation");
+ }
+
+ testRobot.waitForIdle();
+
+ // Method performing auto test operation
+ test();
+
+ disposeTestUI();
+ }
+
+ private static void test() {
+ Point loc = myFrame.getLocationOnScreen();
+
+ testRobot.mouseMove((loc.x + 100), (loc.y + 100));
+
+ // Press the left mouse button
+ testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ myButton.setText("Left button pressed");
+ testRobot.delay(1000);
+
+ // Press the right mouse button
+ testRobot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
+ myButton.setText("Left button pressed + Right button pressed");
+ testRobot.delay(1000);
+
+ // Release the right mouse button
+ testRobot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
+ myButton.setText("Right button released");
+ testRobot.delay(1000);
+
+ // Test whether the button is still pressed
+ if (myButton.getModel().isPressed() == false) {
+ disposeTestUI();
+ throw new RuntimeException("Test Failed!");
+ }
+ }
+
+ private static void disposeTestUI() {
+ myFrame.setVisible(false);
+ myFrame.dispose();
+ }
+
+ public static void constructTestUI() {
+ myFrame = new JFrame();
+ myFrame.setLayout(new BorderLayout());
+ myButton = new JButton("Whatever");
+ myFrame.add(myButton, BorderLayout.CENTER);
+ myFrame.setSize(400, 300);
+ myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ myFrame.setVisible(true);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JEditorPane/5076514/bug5076514.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,58 @@
+/*
+ * 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 5076514 8025430
+ @summary Tests if SecurityManager.checkPermission()
+ used for clipboard access with permission 'accessClipboard'
+ @run main bug5076514
+*/
+
+import java.security.Permission;
+import javax.swing.JEditorPane;
+
+public class bug5076514 {
+ private final static String ACCESS_CLIPBOARD = "accessClipboard";
+ private static boolean isCheckPermissionCalled = false;
+
+ public static void main(String[] args) {
+ System.setSecurityManager(new MySecurityManager());
+ JEditorPane editor = new JEditorPane();
+ editor.copy();
+ if (!isCheckPermissionCalled) {
+ throw new RuntimeException("JEditorPane's clipboard operations "
+ + "didn't call SecurityManager.checkPermission() with "
+ + "permission 'accessClipboard' when there is a security"
+ + " manager installed");
+ }
+ }
+
+ private static class MySecurityManager extends SecurityManager {
+ @Override
+ public void checkPermission(Permission perm) {
+ if (ACCESS_CLIPBOARD.equals(perm.getName())) {
+ isCheckPermissionCalled = true;
+ }
+ }
+ }
+}
--- a/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java Fri May 06 06:23:30 2016 -0700
@@ -30,7 +30,6 @@
* @run main ShellFolderQueriesTest
*/
-import sun.awt.OSInfo;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
@@ -50,7 +49,8 @@
static String scriptEnd = "\"\noShellLink.WindowStyle = 1\noShellLink.Save";
public static void main(String[] args) throws Exception {
- if(OSInfo.getOSType() == OSInfo.OSType.WINDOWS) {
+ if(System.getProperty("os.name").toLowerCase().contains("windows")) {
+ System.out.println("Windows detected: will run shortcut test");
testGet();
testLink();
} else {
--- a/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6439354
+ * @bug 8153056 8152647 6439354
* @summary Verify TitleBorder appearance Color/Visibility for WLAF
* @requires (os.family == "windows")
* @run main/manual TitledBorderTest
@@ -33,6 +33,7 @@
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.util.concurrent.CountDownLatch;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
@@ -41,7 +42,26 @@
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
-public class TitledBorderTest implements ActionListener {
+public class TitledBorderTest {
+
+ public static void main(String args[]) throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ TitledBorder test = new TitledBorder(latch);
+ Thread T1 = new Thread(test);
+ T1.start();
+
+ // wait for latch to complete
+ latch.await();
+
+ if (test.testResult == false) {
+ throw new RuntimeException("User Clicked Fail!"
+ + " TitledBorder Not Valid");
+ }
+ }
+}
+
+class TitledBorder implements Runnable {
private static GridBagLayout layout;
private static JPanel mainControlPanel;
@@ -50,88 +70,98 @@
private static JButton passButton;
private static JButton failButton;
private static JFrame mainFrame;
+ private final CountDownLatch latch;
+ public boolean testResult = false;
- public static void main(String[] args) throws Exception {
- TitledBorderTest titledBorderTest = new TitledBorderTest();
+ public TitledBorder(CountDownLatch latch) throws Exception {
+ this.latch = latch;
}
- public TitledBorderTest() throws Exception {
- createUI();
+ @Override
+ public void run() {
+
+ try {
+ createUI();
+ } catch (Exception ex) {
+ if (mainFrame != null) {
+ mainFrame.dispose();
+ }
+ latch.countDown();
+ throw new RuntimeException("createUI Failed: " + ex.getMessage());
+ }
+
}
public final void createUI() throws Exception {
UIManager.setLookAndFeel("com.sun.java.swing.plaf."
+ "windows.WindowsLookAndFeel");
-
- SwingUtilities.invokeAndWait(() -> {
-
- mainFrame = new JFrame("Window LAF TitledBorder Test");
- layout = new GridBagLayout();
- mainControlPanel = new JPanel(layout);
- resultButtonPanel = new JPanel(layout);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ mainFrame = new JFrame("Window LAF TitledBorder Test");
+ layout = new GridBagLayout();
+ mainControlPanel = new JPanel(layout);
+ resultButtonPanel = new JPanel(layout);
- GridBagConstraints gbc = new GridBagConstraints();
- String instructions
- = "INSTRUCTIONS:"
- + "\n set Windows Theme to HighContrast#1."
- + "\n (ControlPanel->Personalization->High Contrast#1)"
- + "\n If Titled Border(Border Line) is visible then test"
- + " passes else failed.";
+ GridBagConstraints gbc = new GridBagConstraints();
+ String instructions
+ = "INSTRUCTIONS:"
+ + "\n set Windows Theme to HighContrast#1."
+ + "\n (ControlPanel->Personalization->High Contrast#1)"
+ + "\n If Titled Border(Border Line) is visible then test"
+ + " passes else failed.";
- instructionTextArea = new JTextArea();
- instructionTextArea.setText(instructions);
- instructionTextArea.setEnabled(false);
- instructionTextArea.setDisabledTextColor(Color.black);
- instructionTextArea.setBackground(Color.white);
+ instructionTextArea = new JTextArea();
+ instructionTextArea.setText(instructions);
+ instructionTextArea.setEnabled(false);
+ instructionTextArea.setDisabledTextColor(Color.black);
+ instructionTextArea.setBackground(Color.white);
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- mainControlPanel.add(instructionTextArea, gbc);
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
- mainControlPanel.setBorder(BorderFactory.
- createTitledBorder("Titled Border"));
+ mainControlPanel.setBorder(BorderFactory.
+ createTitledBorder("Titled Border"));
- passButton = new JButton("Pass");
- passButton.setActionCommand("Pass");
- passButton.addActionListener(TitledBorderTest.this);
- failButton = new JButton("Fail");
- failButton.setActionCommand("Fail");
- failButton.addActionListener(TitledBorderTest.this);
- gbc.gridx = 0;
- gbc.gridy = 0;
- resultButtonPanel.add(passButton, gbc);
- gbc.gridx = 1;
- gbc.gridy = 0;
- resultButtonPanel.add(failButton, gbc);
+ passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ System.out.println("Pass Button pressed!");
+ testResult = true;
+ mainFrame.dispose();
+ latch.countDown();
- gbc.gridx = 0;
- gbc.gridy = 1;
- mainControlPanel.add(resultButtonPanel, gbc);
+ });
+ failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("Fail Button pressed!");
+ testResult = false;
+ mainFrame.dispose();
+ latch.countDown();
+ }
+ });
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
- mainFrame.add(mainControlPanel);
- mainFrame.pack();
- mainFrame.setVisible(true);
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+ mainFrame.setVisible(true);
+ }
});
+
}
-
- @Override
- public void actionPerformed(ActionEvent evt) {
- if (evt.getSource() instanceof JButton) {
- JButton btn = (JButton) evt.getSource();
- cleanUp();
- switch (btn.getActionCommand()) {
- case "Pass":
- break;
- case "Fail":
- throw new AssertionError("User Clicked Fail!");
- }
- }
- }
-
- private static void cleanUp() {
- mainFrame.dispose();
- }
-
}
--- a/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -104,8 +104,12 @@
e.printStackTrace();
}
for (int i = 0; i < 1000; i++) {
- undoManager.undoOrRedo();
- undoManager.undo();
+ if(undoManager.canUndoOrRedo()) {
+ undoManager.undoOrRedo();
+ }
+ if(undoManager.canUndo()) {
+ undoManager.undo();
+ }
}
System.out.println("t3 done");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/transaction/testng/Driver.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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
+ * @compile -addmods java.transaction
+ * test/transaction/InvalidTransactionExceptionTests.java
+ * test/transaction/TransactionRequiredExceptionTests.java
+ * test/transaction/TransactionRolledbackExceptionTests.java
+ * test/transaction/XAExceptionTests.java
+ * util/SerializedTransactionExceptions.java
+ * @run testng/othervm -addmods java.transaction test.transaction.InvalidTransactionExceptionTests
+ * @run testng/othervm -addmods java.transaction test.transaction.TransactionRequiredExceptionTests
+ * @run testng/othervm -addmods java.transaction test.transaction.TransactionRolledbackExceptionTests
+ * @run testng/othervm -addmods java.transaction util.SerializedTransactionExceptions
+ */
--- a/jdk/test/javax/transaction/testng/TEST.properties Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-# JDBC unit tests uses TestNG
-TestNG.dirs= .
-othervm.dirs= .
-
--- a/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java Fri May 06 06:23:30 2016 -0700
@@ -26,6 +26,7 @@
* @bug 8032884
* @summary Globalbindings optionalProperty="primitive" does not work when minOccurs=0
* @run shell compile-schema.sh
+ * @compile -addmods java.xml.bind XjcOptionalPropertyTest.java
* @run main/othervm XjcOptionalPropertyTest
*/
--- a/jdk/test/javax/xml/jaxp/common/8035437/run.sh Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/jaxp/common/8035437/run.sh Fri May 06 06:23:30 2016 -0700
@@ -34,12 +34,12 @@
-d compile/java.xml -Xmodule:java.xml $TESTSRC/Document.java $TESTSRC/Node.java || exit 1
$COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
- -d exec/java.xml -Xpatch:compile -Xmodule:java.xml $TESTSRC/DocumentImpl.java || exit 2
+ -d exec/java.xml -Xpatch:java.xml=compile/java.xml -Xmodule:java.xml $TESTSRC/DocumentImpl.java || exit 2
$COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
$TESTSRC/AbstractMethodErrorTest.java -d exec || exit 3
-$TESTJAVA/bin/java ${TESTVMOPTS} -Xpatch:exec -cp exec AbstractMethodErrorTest || exit 4
+$TESTJAVA/bin/java ${TESTVMOPTS} -Xpatch:java.xml=exec -cp exec AbstractMethodErrorTest || exit 4
exit 0
--- a/jdk/test/javax/xml/soap/XmlTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/soap/XmlTest.java Fri May 06 06:23:30 2016 -0700
@@ -38,6 +38,8 @@
/*
* @test
+ * @compile -addmods java.xml.ws XmlTest.java
+ * @run main/othervm -addmods java.xml.ws XmlTest
* @summary tests JAF DataHandler can be instantiated; test serialize and
* deserialize SOAP message containing xml attachment
*/
--- a/jdk/test/javax/xml/soap/spi/SAAJFactoryTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/soap/spi/SAAJFactoryTest.java Fri May 06 06:23:30 2016 -0700
@@ -49,29 +49,29 @@
* run main/othervm SAAJFactoryTest saaj.factory.Valid -
* scenario14 javax.xml.soap.MessageFactory=saaj.factory.Valid saaj.factory.Valid2 -
*
- * @build saaj.factory.*
+ * @compile -addmods java.xml.ws saaj/factory/Invalid.java saaj/factory/Valid.java
+ * saaj/factory/Valid2.java saaj/factory/Valid3.java SAAJFactoryTest.java
*
- * @run main/othervm SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl -
- * scenario2 - -
- * @run main/othervm -Djavax.xml.soap.MessageFactory=saaj.factory.Valid SAAJFactoryTest saaj.factory.Valid -
- * scenario5 - -
- * @run main/othervm -Djavax.xml.soap.MessageFactory=saaj.factory.NonExisting SAAJFactoryTest
- * - javax.xml.soap.SOAPException
- * scenario6 - -
- * @run main/othervm -Djavax.xml.soap.MessageFactory=saaj.factory.Invalid SAAJFactoryTest - javax.xml.soap.SOAPException
- * scenario7 - -
- * @run main/othervm SAAJFactoryTest saaj.factory.Valid -
- * scenario8 - saaj.factory.Valid
- * @run main/othervm SAAJFactoryTest saaj.factory.Valid -
- * scenario9 - saaj.factory.Valid
- * @run main/othervm SAAJFactoryTest - javax.xml.soap.SOAPException
- * scenario10 - saaj.factory.NonExisting
- * @run main/othervm SAAJFactoryTest - javax.xml.soap.SOAPException
- * scenario11 - saaj.factory.Invalid
- * @run main/othervm SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl -
- * scenario12 - -
- * @run main/othervm SAAJFactoryTest saaj.factory.Valid -
- * scenario15 - saaj.factory.Valid
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl - scenario2 - -
+ * @run main/othervm -addmods java.xml.ws -Djavax.xml.soap.MessageFactory=saaj.factory.Valid
+ * SAAJFactoryTest saaj.factory.Valid - scenario5 - -
+ * @run main/othervm -addmods java.xml.ws -Djavax.xml.soap.MessageFactory=saaj.factory.NonExisting
+ * SAAJFactoryTest - javax.xml.soap.SOAPException scenario6 - -
+ * @run main/othervm -addmods java.xml.ws -Djavax.xml.soap.MessageFactory=saaj.factory.Invalid
+ * SAAJFactoryTest - javax.xml.soap.SOAPException scenario7 - -
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest saaj.factory.Valid - scenario8 - saaj.factory.Valid
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest saaj.factory.Valid - scenario9 - saaj.factory.Valid
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest - javax.xml.soap.SOAPException scenario10 - saaj.factory.NonExisting
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest - javax.xml.soap.SOAPException scenario11 - saaj.factory.Invalid scenario11 - saaj.factory.Invalid
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl - scenario12 - -
+ * @run main/othervm -addmods java.xml.ws
+ * SAAJFactoryTest saaj.factory.Valid - scenario15 - saaj.factory.Valid
*/
public class SAAJFactoryTest {
--- a/jdk/test/javax/xml/ws/8043129/MailTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/ws/8043129/MailTest.java Fri May 06 06:23:30 2016 -0700
@@ -27,8 +27,8 @@
* @summary JAF initialisation in SAAJ clashing with the one in javax.mail
* @author mkos
* @library javax.mail.jar
- * @build MailTest
- * @run main MailTest
+ * @compile -addmods java.xml.ws MailTest.java
+ * @run main/othervm -addmods java.xml.ws MailTest
*/
import javax.activation.CommandMap;
--- a/jdk/test/javax/xml/ws/clientjar/TestWsImport.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/ws/clientjar/TestWsImport.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,8 @@
* @test
* @bug 8016271 8026405
* @summary wsimport -clientjar does not create portable jar on windows due to hardcoded '\'
- * @run main/othervm TestWsImport
+ * @compile -addmods java.xml.ws TestWsImport.java
+ * @run main/othervm -addmods java.xml.ws TestWsImport
*/
import javax.xml.namespace.QName;
--- a/jdk/test/javax/xml/ws/publish/WSTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/ws/publish/WSTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,8 @@
* @test
* @bug 8146086
* @summary Publishing two webservices on same port fails with "java.net.BindException: Address already in use"
- * @run main/othervm WSTest
+ * @compile -addmods java.xml.ws WSTest.java
+ * @run main/othervm -addmods java.xml.ws WSTest
*/
import javax.jws.WebMethod;
import javax.jws.WebService;
--- a/jdk/test/javax/xml/ws/xsanymixed/Test.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/javax/xml/ws/xsanymixed/Test.java Fri May 06 06:23:30 2016 -0700
@@ -27,7 +27,8 @@
* @summary the content of xs:any content:mixed should remain as is,
* no white space changes and no changes to namespace prefixes
* @run shell compile-wsdl.sh
- * @run main/othervm Test
+ * @compile -addmods java.xml.ws Test.java
+ * @run main/othervm -addmods java.xml.ws Test
*/
import com.sun.net.httpserver.HttpServer;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/java/util/jar/SimpleHttpServer.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.net.httpserver.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Extremely simple server that only performs one task. The server listens for
+ * requests on the ephemeral port. If it sees a request that begins with
+ * "/multi-release.jar", it consumes the request and returns a stream of bytes
+ * representing the jar file multi-release.jar found in "userdir".
+ */
+class SimpleHttpServer {
+ private static final String userdir = System.getProperty("user.dir", ".");
+ private static final Path multirelease = Paths.get(userdir, "multi-release.jar");
+
+ private final HttpServer server;
+
+ public SimpleHttpServer() throws IOException {
+ server = HttpServer.create();
+ }
+
+ public void start() throws IOException {
+ server.bind(new InetSocketAddress(0), 0);
+ server.createContext("/multi-release.jar", t -> {
+ try (InputStream is = t.getRequestBody()) {
+ is.readAllBytes(); // probably not necessary to consume request
+ byte[] bytes = Files.readAllBytes(multirelease);
+ t.sendResponseHeaders(200, bytes.length);
+ try (OutputStream os = t.getResponseBody()) {
+ os.write(bytes);
+ }
+ }
+ });
+ server.setExecutor(null); // creates a default executor
+ server.start();
+ }
+
+ public void stop() {
+ server.stop(0);
+ }
+
+ int getPort() {
+ return server.getAddress().getPort();
+ }
+}
+
--- a/jdk/test/sun/java2d/OpenGL/GradientPaints.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/sun/java2d/OpenGL/GradientPaints.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 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
@@ -23,11 +23,11 @@
/*
* @test
- * @bug 6521533 6525997
+ * @bug 6521533 6525997 7102282
* @summary Verifies that the OGL-accelerated codepaths for GradientPaint,
* LinearGradientPaint, and RadialGradientPaint produce results that are
* sufficiently close to those produced by the software codepaths.
- * @run main/othervm -Dsun.java2d.opengl=True GradientPaints
+ * @run main/othervm -Dsun.java2d.uiScale=1 -Dsun.java2d.opengl=True GradientPaints
* @author campbelc
*/
--- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java Fri May 06 06:23:30 2016 -0700
@@ -26,19 +26,25 @@
* @bug 8132734
* @summary Test that URL connections to multi-release jars can be runtime versioned
* @library /lib/testlibrary/java/util/jar
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer
* @run testng MultiReleaseJarURLConnection
*/
import java.io.IOException;
import java.io.InputStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.net.JarURLConnection;
import java.net.URL;
+import java.net.URLClassLoader;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.jar.JarFile;
+import jdk.Version;
+
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@@ -47,46 +53,78 @@
public class MultiReleaseJarURLConnection {
String userdir = System.getProperty("user.dir",".");
- String file = userdir + "/signed-multi-release.jar";
+ String unversioned = userdir + "/unversioned.jar";
+ String unsigned = userdir + "/multi-release.jar";
+ String signed = userdir + "/signed-multi-release.jar";
+ SimpleHttpServer server;
@BeforeClass
public void initialize() throws Exception {
CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
creator.compileEntries();
+ creator.buildUnversionedJar();
creator.buildMultiReleaseJar();
creator.buildSignedMultiReleaseJar();
+
+ server = new SimpleHttpServer();
+ server.start();
+
}
@AfterClass
public void close() throws IOException {
- Files.delete(Paths.get(userdir, "multi-release.jar"));
- Files.delete(Paths.get(userdir, "signed-multi-release.jar"));
+ // Windows requires server to stop before file is deleted
+ if (server != null)
+ server.stop();
+ Files.delete(Paths.get(unversioned));
+ Files.delete(Paths.get(unsigned));
+ Files.delete(Paths.get(signed));
}
@DataProvider(name = "data")
public Object[][] createData() {
return new Object[][]{
- {"unsigned file", userdir + "/multi-release.jar"},
- {"signed file", userdir + "/signed-multi-release.jar"},
+ {"unversioned", unversioned},
+ {"unsigned", unsigned},
+ {"signed", signed}
};
}
@Test(dataProvider = "data")
- public void testRuntimeVersioning(String ignore, String file) throws Exception {
+ public void testRuntimeVersioning(String style, String file) throws Exception {
String urlFile = "jar:file:" + file + "!/";
- String urlEntry = urlFile + "version/Version.java";
+ String baseUrlEntry = urlFile + "version/Version.java";
+ String rtreturn = "return " + Version.current().major();
+
+ Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8"));
+ // #runtime is "magic" for a multi-release jar, but not for unversioned jar
+ Assert.assertTrue(readAndCompare(new URL(baseUrlEntry + "#runtime"),
+ style.equals("unversioned") ? "return 8" : rtreturn));
+ // #fragment or any other fragment is not magic
+ Assert.assertTrue(readAndCompare(new URL(baseUrlEntry + "#fragment"), "return 8"));
+ // cached entities not affected
+ Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8"));
- Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
- // #runtime is "magic"
- Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9"));
- // #fragment or any other fragment is not magic
- Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8"));
- // cached entities not affected
- Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
+ // the following tests will not work with unversioned jars
+ if (style.equals("unversioned")) return;
+
+ // direct access to versioned entry
+ String versUrlEntry = urlFile + "META-INF/versions/" + Version.current().major()
+ + "/version/Version.java";
+ Assert.assertTrue(readAndCompare(new URL(versUrlEntry), rtreturn));
+ // adding any fragment does not change things
+ Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#runtime"), rtreturn));
+ Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#fragment"), rtreturn));
+
+ // it really doesn't change things
+ versUrlEntry = urlFile + "META-INF/versions/10/version/Version.java";
+ Assert.assertTrue(readAndCompare(new URL(versUrlEntry), "return 10"));
+ Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#runtime"), "return 10"));
+ Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#fragment"), "return 10"));
}
@Test(dataProvider = "data")
- public void testCachedJars(String ignore, String file) throws Exception {
+ public void testCachedJars(String style, String file) throws Exception {
String urlFile = "jar:file:" + file + "!/";
URL rootUrl = new URL(urlFile);
@@ -98,7 +136,11 @@
juc = (JarURLConnection)runtimeUrl.openConnection();
JarFile runtimeJar = juc.getJarFile();
JarFile.Release runtime = runtimeJar.getVersion();
- Assert.assertNotEquals(root, runtime);
+ if (style.equals("unversioned")) {
+ Assert.assertEquals(root, runtime);
+ } else {
+ Assert.assertNotEquals(root, runtime);
+ }
juc = (JarURLConnection)rootUrl.openConnection();
JarFile jar = juc.getJarFile();
@@ -115,6 +157,63 @@
jar.close(); // probably not needed
}
+ @DataProvider(name = "resourcedata")
+ public Object[][] createResourceData() throws Exception {
+ return new Object[][]{
+ {"unversioned", Paths.get(unversioned).toUri().toURL()},
+ {"unsigned", Paths.get(unsigned).toUri().toURL()},
+ {"signed", Paths.get(signed).toUri().toURL()},
+ {"unversioned", new URL("file:" + unversioned)},
+ {"unsigned", new URL("file:" + unsigned)},
+ {"signed", new URL("file:" + signed)},
+ {"unversioned", new URL("jar:file:" + unversioned + "!/")},
+ {"unsigned", new URL("jar:file:" + unsigned + "!/")},
+ {"signed", new URL("jar:file:" + signed + "!/")},
+ // external jar received via http protocol
+ {"http", new URL("jar:http://localhost:" + server.getPort() + "/multi-release.jar!/")},
+ {"http", new URL("http://localhost:" + server.getPort() + "/multi-release.jar")},
+
+ };
+ }
+
+ @Test(dataProvider = "resourcedata")
+ public void testResources(String style, URL url) throws Throwable {
+ //System.out.println(" testing " + style + " url: " + url);
+ URL[] urls = {url};
+ URLClassLoader cldr = new URLClassLoader(urls);
+ Class<?> vcls = cldr.loadClass("version.Version");
+
+ // verify we are loading a runtime versioned class
+ MethodType mt = MethodType.methodType(int.class);
+ MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
+ Assert.assertEquals((int)mh.invoke(vcls.newInstance()),
+ style.equals("unversioned") ? 8 : Version.current().major());
+
+ // now get a resource and verify that we don't have a fragment attached
+ URL vclsUrl = vcls.getResource("/version/Version.class");
+ String fragment = vclsUrl.getRef();
+ Assert.assertNull(fragment);
+
+ // and verify that the the url is a reified pointer to the runtime entry
+ String rep = vclsUrl.toString();
+ //System.out.println(" getResource(\"/version/Version.class\") returned: " + rep);
+ if (style.equals("http")) {
+ Assert.assertTrue(rep.startsWith("jar:http:"));
+ } else {
+ Assert.assertTrue(rep.startsWith("jar:file:"));
+ }
+ String suffix;
+ if (style.equals("unversioned")) {
+ suffix = ".jar!/version/Version.class";
+ } else {
+ suffix = ".jar!/META-INF/versions/" + Version.current().major()
+ + "/version/Version.class";
+ }
+ Assert.assertTrue(rep.endsWith(suffix));
+ cldr.close();
+ }
+
+
private boolean readAndCompare(URL url, String match) throws Exception {
boolean result;
// necessary to do it this way, instead of openStream(), so we can
--- a/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java Fri May 06 06:23:30 2016 -0700
@@ -26,7 +26,6 @@
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
-import javax.xml.bind.DatatypeConverter;
public class SecretKeysBasic extends PKCS11Test {
@@ -131,8 +130,11 @@
System.out.println(info + "> " + key);
System.out.println("\tALGO=" + key.getAlgorithm());
if (key.getFormat() != null) {
- System.out.println("\t[" + key.getFormat() + "] VALUE=" +
- DatatypeConverter.printHexBinary(key.getEncoded()));
+ StringBuilder sb = new StringBuilder();
+ for (byte b : key.getEncoded()) {
+ sb.append(String.format("%02x", b & 0xff));
+ }
+ System.out.println("\t[" + key.getFormat() + "] VALUE=" + sb);
} else {
System.out.println("\tVALUE=n/a");
}
--- a/jdk/test/sun/security/provider/PolicyFile/Modules.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/sun/security/provider/PolicyFile/Modules.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,9 @@
* @test
* @bug 8047771
* @summary check permissions and principals from various modules
- * @run main/othervm/java.security.policy==modules.policy Modules
+ * @compile -addmods java.xml.ws,java.smartcardio Modules.java
+ * @run main/othervm/java.security.policy==modules.policy
+ * -addmods java.xml.ws,java.smartcardio Modules
*/
import java.security.AccessController;
--- a/jdk/test/sun/security/tools/jarsigner/Warning.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/sun/security/tools/jarsigner/Warning.java Fri May 06 06:23:30 2016 -0700
@@ -89,7 +89,7 @@
issueCert("c");
run("jarsigner", "a.jar c")
.shouldContain("chain is not validated. " +
- "Reason: algorithm constraints check failed");
+ "Reason: Algorithm constraints check failed");
recreateJar();
--- a/jdk/test/tools/jar/modularJar/Basic.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jar/modularJar/Basic.java Fri May 06 06:23:30 2016 -0700
@@ -340,43 +340,43 @@
"--file=" + modularJar.toString())
.assertSuccess()
.resultChecker(r -> {
- // Expect similar output: "Name:bar, Requires: foo,...
- // Conceals: jdk.test.foo, jdk.test.foo.internal"
- Pattern p = Pattern.compile("\\s+Name:\\s+bar\\s+Requires:\\s+foo");
+ // Expect similar output: "bar, requires mandated foo, ...
+ // conceals jdk.test.foo, conceals jdk.test.foo.internal"
+ Pattern p = Pattern.compile("\\s+bar\\s+requires\\s++foo");
assertTrue(p.matcher(r.output).find(),
- "Expecting to find \"Name: bar, Requires: foo,...\"",
+ "Expecting to find \"bar, requires foo,...\"",
"in output, but did not: [" + r.output + "]");
p = Pattern.compile(
- "Conceals:\\s+jdk.test.foo\\s+jdk.test.foo.internal");
+ "conceals\\s+jdk.test.foo\\s+conceals\\s+jdk.test.foo.internal");
assertTrue(p.matcher(r.output).find(),
- "Expecting to find \"Conceals: jdk.test.foo,...\"",
+ "Expecting to find \"conceals jdk.test.foo,...\"",
"in output, but did not: [" + r.output + "]");
});
}
@Test
- public void dependencesFooBar() throws IOException {
+ public void hashBarInFooModule() throws IOException {
Path mp = Paths.get("dependencesFooBar");
createTestDir(mp);
- Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
- Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+ Path modClasses = MODULE_CLASSES.resolve(BAR.moduleName);
+ Path modularJar = mp.resolve(BAR.moduleName + ".jar");
+ jar("--create",
+ "--file=" + modularJar.toString(),
+ "--main-class=" + BAR.mainClass,
+ "--module-version=" + BAR.version,
+ "--no-manifest",
+ "-C", modClasses.toString(), ".")
+ .assertSuccess();
+
+ modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+ modularJar = mp.resolve(FOO.moduleName + ".jar");
jar("--create",
"--file=" + modularJar.toString(),
"--main-class=" + FOO.mainClass,
"--module-version=" + FOO.version,
- "--no-manifest",
- "-C", modClasses.toString(), ".")
- .assertSuccess();
-
- modClasses = MODULE_CLASSES.resolve(BAR.moduleName);
- modularJar = mp.resolve(BAR.moduleName + ".jar");
- jar("--create",
- "--file=" + modularJar.toString(),
- "--main-class=" + BAR.mainClass,
- "--module-version=" + BAR.version,
"--modulepath=" + mp.toString(),
- "--hash-dependencies=" + "foo", // dependency on foo
+ "--hash-modules=" + "bar",
"--no-manifest",
"-C", modClasses.toString(), ".")
.assertSuccess();
@@ -392,49 +392,49 @@
}
@Test
- public void badDependencyFooBar() throws IOException {
+ public void invalidHashInFooModule() throws IOException {
Path mp = Paths.get("badDependencyFooBar");
createTestDir(mp);
- Path fooClasses = MODULE_CLASSES.resolve(FOO.moduleName);
- Path fooJar = mp.resolve(FOO.moduleName + ".jar");
- jar("--create",
- "--file=" + fooJar.toString(),
- "--main-class=" + FOO.mainClass,
- "--module-version=" + FOO.version,
- "--no-manifest",
- "-C", fooClasses.toString(), ".").assertSuccess();
-
Path barClasses = MODULE_CLASSES.resolve(BAR.moduleName);
Path barJar = mp.resolve(BAR.moduleName + ".jar");
jar("--create",
"--file=" + barJar.toString(),
"--main-class=" + BAR.mainClass,
"--module-version=" + BAR.version,
- "--modulepath=" + mp.toString(),
- "--hash-dependencies=" + "foo", // dependency on foo
"--no-manifest",
"-C", barClasses.toString(), ".").assertSuccess();
- // Rebuild foo.jar with a change that will cause its hash to be different
- FileUtils.deleteFileWithRetry(fooJar);
+ Path fooClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+ Path fooJar = mp.resolve(FOO.moduleName + ".jar");
jar("--create",
"--file=" + fooJar.toString(),
"--main-class=" + FOO.mainClass,
- "--module-version=" + FOO.version + ".1", // a newer version
+ "--module-version=" + FOO.version,
+ "--modulepath=" + mp.toString(),
+ "--hash-modules=" + "bar",
"--no-manifest",
"-C", fooClasses.toString(), ".").assertSuccess();
+ // Rebuild bar.jar with a change that will cause its hash to be different
+ FileUtils.deleteFileWithRetry(barJar);
+ jar("--create",
+ "--file=" + barJar.toString(),
+ "--main-class=" + BAR.mainClass,
+ "--module-version=" + BAR.version + ".1", // a newer version
+ "--no-manifest",
+ "-C", barClasses.toString(), ".").assertSuccess();
+
java(mp, BAR.moduleName + "/" + BAR.mainClass,
"-XaddExports:java.base/jdk.internal.module=bar")
.assertFailure()
.resultChecker(r -> {
// Expect similar output: "java.lang.module.ResolutionException: Hash
- // of foo (WdktSIQSkd4+CEacpOZoeDrCosMATNrIuNub9b5yBeo=) differs to
+ // of bar (WdktSIQSkd4+CEacpOZoeDrCosMATNrIuNub9b5yBeo=) differs to
// expected hash (iepvdv8xTeVrFgMtUhcFnmetSub6qQHCHc92lSaSEg0=)"
- Pattern p = Pattern.compile(".*Hash of foo.*differs to expected hash.*");
+ Pattern p = Pattern.compile(".*Hash of bar.*differs to expected hash.*");
assertTrue(p.matcher(r.output).find(),
- "Expecting error message containing \"Hash of foo ... differs to"
+ "Expecting error message containing \"Hash of bar ... differs to"
+ " expected hash...\" but got: [", r.output + "]");
});
}
@@ -454,7 +454,7 @@
jar("--create",
"--file=" + modularJar.toString(),
- "--hash-dependencies=" + ".*", // no module-info.class
+ "--hash-modules=" + ".*", // no module-info.class
"-C", modClasses.toString(), "jdk")
.assertFailure(); // TODO: expected failure message
}
--- a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java Fri May 06 06:23:30 2016 -0700
@@ -30,7 +30,7 @@
import java.util.Optional;
import java.util.StringJoiner;
-import jdk.internal.module.Hasher;
+import jdk.internal.module.ModuleHashes;
import jdk.test.bar.internal.Message;
public class Bar {
@@ -43,10 +43,11 @@
Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
m.setAccessible(true);
- Optional<Hasher.DependencyHashes> optHashes =
- (Optional<Hasher.DependencyHashes>) m.invoke(md);
+ ModuleDescriptor foo = jdk.test.foo.Foo.class.getModule().getDescriptor();
+ Optional<ModuleHashes> oHashes =
+ (Optional<ModuleHashes>) m.invoke(foo);
- System.out.println("hashes:" + optHashes.get().hashFor("foo"));
+ System.out.println("hashes:" + oHashes.get().hashFor("bar"));
StringJoiner sj = new StringJoiner(",");
md.conceals().forEach(sj::add);
--- a/jdk/test/tools/jlink/ImageFileCreatorTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java Fri May 06 06:23:30 2016 -0700
@@ -214,14 +214,12 @@
}
@Override
- public void storeFiles(Pool content, String bom) {
-
+ public void storeFiles(Pool content) {
}
-
};
ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
- null, Collections.emptyList(), "");
+ null, Collections.emptyList());
ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
}
--- a/jdk/test/tools/jlink/IntegrationTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jlink/IntegrationTest.java Fri May 06 06:23:30 2016 -0700
@@ -241,7 +241,7 @@
lst.add(new MyPostProcessor());
}
// Image builder
- DefaultImageBuilder builder = new DefaultImageBuilder(true, output);
+ DefaultImageBuilder builder = new DefaultImageBuilder(output);
PluginsConfiguration plugins
= new Jlink.PluginsConfiguration(lst, builder, null);
@@ -254,10 +254,6 @@
if (!jimage.exists()) {
throw new AssertionError("jimage not generated");
}
- File bom = new File(output.toString(), "bom");
- if (!bom.exists()) {
- throw new AssertionError("bom not generated");
- }
File release = new File(output.toString(), "release");
if (!release.exists()) {
throw new AssertionError("release not generated");
@@ -311,7 +307,7 @@
}
// Image builder
- DefaultImageBuilder builder = new DefaultImageBuilder(false, output);
+ DefaultImageBuilder builder = new DefaultImageBuilder(output);
PluginsConfiguration plugins
= new Jlink.PluginsConfiguration(lst, builder, null);
@@ -359,7 +355,7 @@
}
// Image builder
- DefaultImageBuilder builder = new DefaultImageBuilder(false, output);
+ DefaultImageBuilder builder = new DefaultImageBuilder(output);
PluginsConfiguration plugins
= new Jlink.PluginsConfiguration(lst, builder, null);
boolean failed = false;
--- a/jdk/test/tools/jlink/JLink2Test.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jlink/JLink2Test.java Fri May 06 06:23:30 2016 -0700
@@ -66,8 +66,6 @@
// This test case must be first one, the JlinkTask is clean
// and reveals possible bug related to plugin options in defaults
- // e. g.: --genbom
- testBomFile(helper);
testSameNames(helper);
testModulePath(helper);
testOptions();
@@ -136,35 +134,6 @@
validator.validate();
}
- private static void testBomFile(Helper helper) throws Exception {
- String[] userOptions = {
- "--compress",
- "2",
- "--addmods",
- "bomzip",
- "--strip-debug",
- "--genbom",
- "--exclude-resources",
- "*.jcov,*/META-INF/*"};
- String moduleName = "bomzip";
- helper.generateDefaultJModule(moduleName, "composite2");
- Path imgDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
- helper.checkImage(imgDir, moduleName, userOptions, null, null);
- File bom = new File(imgDir.toFile(), "bom");
- if (!bom.exists()) {
- throw new RuntimeException(bom.getAbsolutePath() + " not generated");
- }
- String bomcontent = new String(Files.readAllBytes(bom.toPath()));
- if (!bomcontent.contains("--strip-debug")
- || !bomcontent.contains("--compress")
- || !bomcontent.contains("--genbom")
- || !bomcontent.contains("--exclude-resources *.jcov,"
- + "*/META-INF/*")
- || !bomcontent.contains("--addmods bomzip")) {
- throw new Exception("Not expected content in " + bom);
- }
- }
-
private static void testOptions() throws Exception {
List<Plugin> builtInPlugins = new ArrayList<>();
builtInPlugins.addAll(PluginRepository.getPlugins(Layer.boot()));
--- a/jdk/test/tools/jlink/JLinkTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jlink/JLinkTest.java Fri May 06 06:23:30 2016 -0700
@@ -204,7 +204,7 @@
String[] userOptions = {"--compress", "invalid"};
String moduleName = "invalidCompressLevel";
helper.generateDefaultJModule(moduleName, "composite2");
- helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid level invalid");
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid compression level invalid");
}
// @file
--- a/jdk/test/tools/jlink/hashes/HashesTest.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/**
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary Test the recording and checking of dependency hashes
- * @author Andrei Eremeev
- * @library /lib/testlibrary
- * @modules java.base/jdk.internal.module
- * jdk.jlink/jdk.tools.jlink
- * jdk.jlink/jdk.tools.jmod
- * jdk.compiler
- * @ignore
- * @build jdk.testlibrary.ProcessTools jdk.testlibrary.OutputAnalyzer CompilerUtils
- * @run main HashesTest
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-public class HashesTest {
-
- private final Path jdkHome = Paths.get(System.getProperty("test.jdk"));
- private final Path stdJmods = jdkHome.resolve("jmods");
- private final Path testSrc = Paths.get(System.getProperty("test.src"));
- private final Path modSrc = testSrc.resolve("src");
- private final Path newModSrc = testSrc.resolve("newsrc");
- private final Path classes = Paths.get("classes");
- private final Path jmods = Paths.get("jmods");
-
- public static void main(String[] args) throws Exception {
- new HashesTest().run();
- }
-
- private void run() throws Exception {
- if (!Files.exists(stdJmods)) {
- return;
- }
- Files.createDirectories(jmods);
- Path m1Classes = classes.resolve("m1");
- Path m2Classes = classes.resolve("m2");
- Path m3Classes = classes.resolve("not_matched");
- // build the second module
- compileClasses(modSrc, m2Classes);
- runJmod(m2Classes.toString(), m2Classes.getFileName().toString());
-
- // build the third module
- compileClasses(modSrc, m3Classes);
- runJmod(m3Classes.toString(), m3Classes.getFileName().toString());
-
- compileClasses(modSrc, m1Classes, "-mp", jmods.toString());
- runJmod(m1Classes.toString(), m1Classes.getFileName().toString(),
- "--modulepath", jmods.toString(), "--hash-dependencies", "m2");
- runJava(0, "-mp", jmods.toString(), "-m", "m1/org.m1.Main");
-
- deleteDirectory(m3Classes);
- Files.delete(jmods.resolve("not_matched.jmod"));
-
- // build the new third module
- compileClasses(newModSrc, m3Classes);
- runJmod(m3Classes.toString(), m3Classes.getFileName().toString());
- runJava(0, "-mp", jmods.toString(), "-m", "m1/org.m1.Main");
-
- deleteDirectory(m2Classes);
- Files.delete(jmods.resolve("m2.jmod"));
-
- compileClasses(newModSrc, m2Classes);
- runJmod(m2Classes.toString(), m2Classes.getFileName().toString());
-
- runJava(1, "-mp", jmods.toString(), "-m", "m1/org.m1.Main");
-
- if (jdk.tools.jlink.internal.Main.run(new String[]{
- "--modulepath", stdJmods.toString() + File.pathSeparator + jmods.toString(),
- "--addmods", "m1", "--output", "myimage"}, new PrintWriter(System.out)) == 0) {
- throw new AssertionError("Expected failure. rc = 0");
- }
- }
-
- private void deleteDirectory(Path dir) throws IOException {
- Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- Files.delete(file);
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
- Files.delete(dir);
- return FileVisitResult.CONTINUE;
- }
- });
- }
-
- private void runJava(int expectedExitCode, String... args) throws Exception {
- OutputAnalyzer analyzer = ProcessTools.executeTestJava(args);
- if (analyzer.getExitValue() != expectedExitCode) {
- throw new AssertionError("Expected exit code: " + expectedExitCode +
- ", got: " + analyzer.getExitValue());
- }
- }
-
- private void compileClasses(Path src, Path output, String... options) throws IOException {
- List<String> args = new ArrayList<>();
- Collections.addAll(args, options);
- Collections.addAll(args, "-d", output.toString());
- args.add(src.toString());
- System.out.println("javac options: " + args.stream().collect(Collectors.joining(" ")));
- if (!CompilerUtils.compile(src.resolve(output.getFileName()), output, options)) {
- throw new AssertionError("Compilation failure. See log.");
- }
- }
-
- private void runJmod(String cp, String modName, String... options) {
- List<String> args = new ArrayList<>();
- args.add("create");
- Collections.addAll(args, options);
- Collections.addAll(args, "--class-path", cp,
- jmods + File.separator + modName + ".jmod");
- int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out);
- System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" ")));
- if (rc != 0) {
- throw new AssertionError("Jmod failed: rc = " + rc);
- }
- }
-}
--- a/jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m2 {
- exports org.m2;
-}
--- a/jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m2;
-
-public class Util {
- private Util() { }
-
- public static String timeOfDay() {
- return "Time for a beer";
- }
-}
--- a/jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module not_matched {
- exports org.not_matched;
-}
--- a/jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.not_matched;
-
-public class Name {
- private Name() { }
-
- public static String name() {
- return "new_module";
- }
-}
--- a/jdk/test/tools/jlink/hashes/src/m1/module-info.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m1 {
- requires m2;
- requires not_matched;
-}
--- a/jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m1;
-
-import org.m2.Util;
-import org.not_matched.Name;
-
-public class Main {
- public static void main(String[] args) {
- System.out.println(Util.timeOfDay());
- System.out.println(Name.name());
- }
-}
--- a/jdk/test/tools/jlink/hashes/src/m2/module-info.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m2 {
- exports org.m2;
-}
--- a/jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m2;
-
-public class Util {
- private Util() { }
-
- public static String timeOfDay() {
- return "Time for lunch";
- }
-}
--- a/jdk/test/tools/jlink/hashes/src/not_matched/module-info.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module not_matched {
- exports org.not_matched;
-}
--- a/jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.not_matched;
-
-public class Name {
- private Name() { }
-
- public static String name() {
- return "old_module";
- }
-}
--- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java Fri May 06 06:23:30 2016 -0700
@@ -101,9 +101,8 @@
}
Path root = new File(".").toPath();
- DefaultImageBuilder imgbuilder = new DefaultImageBuilder(false,
- root);
- imgbuilder.storeFiles(pool, "");
+ DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root);
+ imgbuilder.storeFiles(pool);
if (lic.exists()) {
File license = new File(root.toFile(), "LICENSE");
--- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Fri May 06 06:23:30 2016 -0700
@@ -36,6 +36,7 @@
/*
* @test
+ * @bug 8152143 8152704 8155649
* @summary IncludeLocalesPlugin tests
* @author Naoto Sato
* @library ../../lib
@@ -55,15 +56,17 @@
private final static String moduleName = "IncludeLocalesTest";
private static Helper helper;
private final static int INCLUDE_LOCALES_OPTION = 0;
- private final static int EXPECTED_LOCATIONS = 1;
- private final static int UNEXPECTED_PATHS = 2;
- private final static int AVAILABLE_LOCALES = 3;
- private final static int ERROR_MESSAGE = 4;
+ private final static int ADDMODS_OPTION = 1;
+ private final static int EXPECTED_LOCATIONS = 2;
+ private final static int UNEXPECTED_PATHS = 3;
+ private final static int AVAILABLE_LOCALES = 4;
+ private final static int ERROR_MESSAGE = 5;
private final static Object[][] testData = {
// without --include-locales option: should include all locales
{
"",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
@@ -144,6 +147,7 @@
// All English/Japanese locales
{
"--include-locales=en,ja",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
@@ -174,6 +178,7 @@
// All locales in India
{
"--include-locales=*-IN",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_en_IN.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_hi_IN.class",
@@ -201,7 +206,9 @@
},
// Thai
- {"--include-locales=th",
+ {
+ "--include-locales=th",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
"/jdk.localedata/sun/text/resources/thai_dict",
@@ -221,7 +228,9 @@
},
// Hong Kong
- {"--include-locales=zh-HK",
+ {
+ "--include-locales=zh-HK",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_zh.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_zh_HK.class",
@@ -244,7 +253,9 @@
},
// Norwegian
- {"--include-locales=nb,nn,no",
+ {
+ "--include-locales=nb,nn,no",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_no.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_no_NO.class",
@@ -268,7 +279,9 @@
},
// Hebrew/Indonesian/Yiddish
- {"--include-locales=he,id,yi",
+ {
+ "--include-locales=he,id,yi",
+ "jdk.localedata",
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_in.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_in_ID.class",
@@ -294,7 +307,9 @@
},
// Error case: No matching locales
- {"--include-locales=xyz",
+ {
+ "--include-locales=xyz",
+ "jdk.localedata",
null,
null,
null,
@@ -304,7 +319,9 @@
},
// Error case: Invalid argument
- {"--include-locales=en,zh_HK",
+ {
+ "--include-locales=en,zh_HK",
+ "jdk.localedata",
null,
null,
null,
@@ -312,6 +329,18 @@
PluginsResourceBundle.getMessage("include-locales.invalidtag"), "zh_HK"))
.getMessage(),
},
+
+ // Error case: jdk.localedata is not added
+ {
+ "--include-locales=en-US",
+ "java.base",
+ null,
+ null,
+ null,
+ new PluginException(
+ PluginsResourceBundle.getMessage("include-locales.localedatanotfound"))
+ .getMessage(),
+ },
};
public static void main(String[] args) throws Exception {
@@ -328,7 +357,7 @@
Result result = JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
- .addMods("jdk.localedata")
+ .addMods((String)data[ADDMODS_OPTION])
.option((String)data[INCLUDE_LOCALES_OPTION])
.call();
--- a/jdk/test/tools/jmod/JmodNegativeTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/jmod/JmodNegativeTest.java Fri May 06 06:23:30 2016 -0700
@@ -76,7 +76,7 @@
jmod()
.assertFailure()
.resultChecker(r ->
- assertContains(r.output, "Error: one of create, list, or describe must be specified")
+ assertContains(r.output, "Error: one of create, list, describe, or hash must be specified")
);
}
@@ -85,7 +85,7 @@
jmod("badAction")
.assertFailure()
.resultChecker(r ->
- assertContains(r.output, "Error: mode must be one of create, list, or describe")
+ assertContains(r.output, "Error: mode must be one of create, list, describe, or hash")
);
jmod("--badOption")
@@ -170,14 +170,14 @@
}
@Test
- public void testHashDependenciesModulePathNotSpecified() {
+ public void testHashModulesModulePathNotSpecified() {
jmod("create",
- "--hash-dependencies", "anyPattern.*",
+ "--hash-modules", "anyPattern.*",
"output.jmod")
.assertFailure()
.resultChecker(r ->
assertContains(r.output, "Error: --module-path must be "
- +"specified when hashing dependencies")
+ +"specified when hashing modules")
);
}
@@ -317,7 +317,7 @@
}
@Test
- public void testDependencyNotFound() throws IOException {
+ public void testNoModuleHash() throws IOException {
Path jmod = MODS_DIR.resolve("output.jmod");
FileUtils.deleteFileIfExistsWithRetry(jmod);
Path emptyDir = Paths.get("empty");
@@ -328,13 +328,12 @@
jmod("create",
"--class-path", cp,
- "--hash-dependencies", ".*",
+ "--hash-modules", ".*",
"--modulepath", emptyDir.toString(),
jmod.toString())
- .assertFailure()
.resultChecker(r ->
- assertContains(r.output, "Hashing module foo dependencies, "
- + "unable to find module java.base on module path")
+ assertContains(r.output, "No hashes recorded: " +
+ "no module specified for hashing depends on foo")
);
}
@@ -350,13 +349,10 @@
jmod("create",
"--class-path", cp,
- "--hash-dependencies", ".*",
+ "--hash-modules", ".*",
"--modulepath", MODS_DIR.toString(),
jmod.toString())
- .assertFailure()
- .resultChecker(r ->
- assertContains(r.output, "Error: error reading module path")
- );
+ .assertFailure();
} finally {
FileUtils.deleteFileWithRetry(empty);
}
@@ -371,7 +367,7 @@
Files.createFile(file);
jmod("create",
- "--hash-dependencies", ".*",
+ "--hash-modules", ".*",
"--modulepath", file.toString(),
jmod.toString())
.assertFailure()
@@ -388,7 +384,7 @@
List<Supplier<JmodResult>> tasks = Arrays.asList(
() -> jmod("create",
- "--hash-dependencies", "anyPattern",
+ "--hash-modules", "anyPattern",
"--modulepath", "doesNotExist",
"output.jmod"),
() -> jmod("create",
@@ -436,7 +432,7 @@
List<Supplier<JmodResult>> tasks = Arrays.asList(
() -> jmod("create",
- "--hash-dependencies", "anyPattern",
+ "--hash-modules", "anyPattern",
"--modulepath","empty" + pathSeparator + "doesNotExist",
"output.jmod"),
() -> jmod("create",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/HashesTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,213 @@
+/**
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test the recording and checking of module hashes
+ * @author Andrei Eremeev
+ * @library /lib/testlibrary
+ * @modules java.base/jdk.internal.module
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jmod
+ * jdk.compiler
+ * @build CompilerUtils
+ * @run testng HashesTest
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Method;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.module.ModuleHashes;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class HashesTest {
+
+ private final Path testSrc = Paths.get(System.getProperty("test.src"));
+ private final Path modSrc = testSrc.resolve("src");
+ private final Path mods = Paths.get("mods");
+ private final Path jmods = Paths.get("jmods");
+ private final String[] modules = new String[] { "m1", "m2", "m3"};
+
+ private static Method hashesMethod;
+ @BeforeTest
+ private void setup() throws Exception {
+ if (Files.exists(jmods)) {
+ deleteDirectory(jmods);
+ }
+ Files.createDirectories(jmods);
+
+ // build m2, m3 required by m1
+ compileModule("m2", modSrc);
+ jmod("m2");
+
+ compileModule("m3", modSrc);
+ jmod("m3");
+
+ // build m1
+ compileModule("m1", modSrc);
+ // no hash is recorded since m1 has outgoing edges
+ jmod("m1", "--modulepath", jmods.toString(), "--hash-modules", ".*");
+
+ // compile org.bar and org.foo
+ compileModule("org.bar", modSrc);
+ compileModule("org.foo", modSrc);
+
+ try {
+ hashesMethod = ModuleDescriptor.class.getDeclaredMethod("hashes");
+ hashesMethod.setAccessible(true);
+ } catch (ReflectiveOperationException x) {
+ throw new InternalError(x);
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ for (String mn : modules) {
+ assertFalse(hashes(mn).isPresent());
+ }
+
+ // hash m1 in m2
+ jmod("m2", "--modulepath", jmods.toString(), "--hash-modules", "m1");
+ checkHashes(hashes("m2").get(), "m1");
+
+ // hash m1 in m2
+ jmod("m2", "--modulepath", jmods.toString(), "--hash-modules", ".*");
+ checkHashes(hashes("m2").get(), "m1");
+
+ // create m2.jmod with no hash
+ jmod("m2");
+ // run jmod hash command to hash m1 in m2 and m3
+ runJmod(Arrays.asList("hash", "--modulepath", jmods.toString(),
+ "--hash-modules", ".*"));
+ checkHashes(hashes("m2").get(), "m1");
+ checkHashes(hashes("m3").get(), "m1");
+
+ jmod("org.bar");
+ jmod("org.foo");
+
+ jmod("org.bar", "--modulepath", jmods.toString(), "--hash-modules", "org.*");
+ checkHashes(hashes("org.bar").get(), "org.foo");
+
+ jmod("m3", "--modulepath", jmods.toString(), "--hash-modules", ".*");
+ checkHashes(hashes("m3").get(), "org.foo", "org.bar", "m1");
+ }
+
+ private void checkHashes(ModuleHashes hashes, String... hashModules) {
+ assertTrue(hashes.names().equals(Set.of(hashModules)));
+ }
+
+ private Optional<ModuleHashes> hashes(String name) throws Exception {
+ ModuleFinder finder = ModuleFinder.of(jmods.resolve(name + ".jmod"));
+ if (finder instanceof ConfigurableModuleFinder) {
+ ((ConfigurableModuleFinder) finder)
+ .configurePhase(ConfigurableModuleFinder.Phase.LINK_TIME);
+ }
+ ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new);
+ ModuleReader reader = mref.open();
+ try (InputStream in = reader.open("module-info.class").get()) {
+ ModuleDescriptor md = ModuleDescriptor.read(in);
+ Optional<ModuleHashes> hashes =
+ (Optional<ModuleHashes>) hashesMethod.invoke(md);
+ System.out.format("hashes in module %s %s%n", name,
+ hashes.isPresent() ? "present" : "absent");
+ if (hashes.isPresent()) {
+ hashes.get().names().stream()
+ .sorted()
+ .forEach(n -> System.out.format(" %s %s%n", n, hashes.get().hashFor(n)));
+ }
+ return hashes;
+ } finally {
+ reader.close();
+ }
+ }
+
+ private void deleteDirectory(Path dir) throws IOException {
+ Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException
+ {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+ throws IOException
+ {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+
+ private void compileModule(String moduleName, Path src) throws IOException {
+ Path msrc = src.resolve(moduleName);
+ assertTrue(CompilerUtils.compile(msrc, mods, "-modulesourcepath", src.toString()));
+ }
+
+ private void jmod(String moduleName, String... options) throws IOException {
+ Path mclasses = mods.resolve(moduleName);
+ Path outfile = jmods.resolve(moduleName + ".jmod");
+ List<String> args = new ArrayList<>();
+ args.add("create");
+ Collections.addAll(args, options);
+ Collections.addAll(args, "--class-path", mclasses.toString(),
+ outfile.toString());
+
+ if (Files.exists(outfile))
+ Files.delete(outfile);
+
+ runJmod(args);
+ }
+
+ private void runJmod(List<String> args) {
+ int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out);
+ System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" ")));
+ if (rc != 0) {
+ throw new AssertionError("Jmod failed: rc = " + rc);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/m1/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+ requires m2;
+ requires m3;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.m1;
+
+import org.m2.Util;
+import org.m3.Name;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println(Util.timeOfDay());
+ System.out.println(Name.name());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/m2/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+ exports org.m2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/m2/org/m2/Util.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.m2;
+
+public class Util {
+ private Util() { }
+
+ public static String timeOfDay() {
+ return "Time for lunch";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/m3/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m3 {
+ exports org.m3;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.m3;
+
+public class Name {
+ private Name() { }
+
+ public static String name() {
+ return "m3";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+module org.bar {
+ requires public m1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+module org.foo {
+ requires public org.bar;
+}
--- a/jdk/test/tools/launcher/ToolsOpts.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/launcher/ToolsOpts.java Fri May 06 06:23:30 2016 -0700
@@ -151,29 +151,26 @@
init();
TestResult tr;
int jpos = -1;
+ String xPatch = "-J-Xpatch:jdk.compiler=jdk.compiler";
for (String arg[] : optionPatterns) {
jpos = indexOfJoption(arg);
//Build a cmd string for output in results reporting.
- String cmdString = javacCmd + " -J-Xpatch:.";
+ String cmdString = javacCmd + " " + xPatch;
for (String opt : arg) {
cmdString = cmdString.concat(" " + opt);
}
switch (arg.length) {
case 1:
- tr = doExec(javacCmd, "-J-Xpatch:.",
- arg[0]);
+ tr = doExec(javacCmd, xPatch, arg[0]);
break;
case 2:
- tr = doExec(javacCmd, "-J-Xpatch:.",
- arg[0], arg[1]);
+ tr = doExec(javacCmd, xPatch, arg[0], arg[1]);
break;
case 3:
- tr = doExec(javacCmd, "-J-Xpatch:.",
- arg[0], arg[1], arg[2]);
+ tr = doExec(javacCmd, xPatch, arg[0], arg[1], arg[2]);
break;
case 4:
- tr = doExec(javacCmd, "-J-Xpatch:.",
- arg[0], arg[1], arg[2], arg[3]);
+ tr = doExec(javacCmd, xPatch, arg[0], arg[1], arg[2], arg[3]);
break;
default:
tr = null;
--- a/jdk/test/tools/launcher/modules/addmods/AddModsTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/launcher/modules/addmods/AddModsTest.java Fri May 06 06:23:30 2016 -0700
@@ -47,120 +47,179 @@
private static final String TEST_SRC = System.getProperty("test.src");
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
- private static final Path MODS_DIR = Paths.get("mods");
-
- // the module name of the library module
- private static final String LIB_MODULE = "lib";
+ private static final Path MODS1_DIR = Paths.get("mods1");
+ private static final Path MODS2_DIR = Paths.get("mods2");
- // application source directory
- private static final String APP_SRC = "app";
+ // test module / main class
+ private static final String TEST_MODULE = "test";
+ private static final String TEST_MAIN_CLASS = "test.Main";
+ private static final String TEST_MID = TEST_MODULE + "/" + TEST_MAIN_CLASS;
- // application is compiled to classes
- private static final Path CLASSES_DIR = Paths.get("classes");
-
- // application main class
- private static final String MAIN_CLASS = "app.Main";
+ // logger module
+ private static final String LOGGER_MODULE = "logger";
@BeforeTest
public void compile() throws Exception {
-
- // javac -d mods/$LIB_MODULE src/$LIB_MODULE/**
+ // javac -d mods1/test src/test/**
boolean compiled = CompilerUtils.compile(
- SRC_DIR.resolve(LIB_MODULE),
- MODS_DIR.resolve(LIB_MODULE)
+ SRC_DIR.resolve(TEST_MODULE),
+ MODS1_DIR.resolve(TEST_MODULE)
);
- assertTrue(compiled, "library module did not compile");
+ assertTrue(compiled, "test did not compile");
- // javac -d classes -mp mods src/$APP_DIR/**
- compiled = CompilerUtils.compile(
- SRC_DIR.resolve(APP_SRC),
- CLASSES_DIR,
- "-mp", MODS_DIR.toString(),
- "-addmods", LIB_MODULE
+ // javac -d mods1/logger src/logger/**
+ compiled= CompilerUtils.compile(
+ SRC_DIR.resolve(LOGGER_MODULE),
+ MODS2_DIR.resolve(LOGGER_MODULE)
);
- assertTrue(compiled, "app did not compile");
+ assertTrue(compiled, "test did not compile");
}
/**
- * Basic test of -addmods ALL-SYSTEM, using the output of -listmods to
- * check that the a sample of the system modules are resolved.
+ * Basic test of -addmods ALL-DEFAULT. Module java.sql should be
+ * resolved and the types in that module should be visible.
*/
- public void testAddSystemModules() throws Exception {
-
- executeTestJava("-addmods", "ALL-SYSTEM",
- "-listmods",
- "-m", "java.base")
- .outputTo(System.out)
- .errorTo(System.out)
- .shouldContain("java.sql")
- .shouldContain("java.corba");
+ public void testAddDefaultModules1() throws Exception {
- // no exit value to check as -m java.base will likely fail
- }
-
-
- /**
- * Run application on class path that makes use of module on the
- * application module path. Uses {@code -addmods lib}
- */
- public void testRunWithAddMods() throws Exception {
-
- // java -mp mods -addmods lib -cp classes app.Main
+ // java -addmods ALL-DEFAULT -mp mods1 -m test ...
int exitValue
- = executeTestJava("-mp", MODS_DIR.toString(),
- "-addmods", LIB_MODULE,
- "-cp", CLASSES_DIR.toString(),
- MAIN_CLASS)
+ = executeTestJava("-mp", MODS1_DIR.toString(),
+ "-addmods", "ALL-DEFAULT",
+ "-m", TEST_MID,
+ "java.sql.Connection")
.outputTo(System.out)
.errorTo(System.out)
.getExitValue();
assertTrue(exitValue == 0);
-
}
/**
- * Run application on class path that makes use of module on the
- * application module path. Uses {@code -addmods ALL-MODULE-PATH}.
+ * Basic test of -addmods ALL-DEFAULT. Module java.annotations.common
+ * should not resolved and so the types in that module should not be
+ * visible.
*/
- public void testAddAllModulePath() throws Exception {
+ public void testAddDefaultModules2() throws Exception {
+
+ // java -addmods ALL-DEFAULT -mp mods1 -m test ...
+ int exitValue
+ = executeTestJava("-mp", MODS1_DIR.toString(),
+ "-addmods", "ALL-DEFAULT",
+ "-m", TEST_MID,
+ "javax.annotation.Generated")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .shouldContain("ClassNotFoundException")
+ .getExitValue();
- // java -mp mods -addmods lib -cp classes app.Main
+ assertTrue(exitValue != 0);
+ }
+
+ /**
+ * Basic test of -addmods ALL-SYSTEM. All system modules should be resolved
+ * and thus all types in those modules should be visible.
+ */
+ public void testAddSystemModules() throws Exception {
+
+ // java -addmods ALL-SYSTEM -mp mods1 -m test ...
int exitValue
- = executeTestJava("-mp", MODS_DIR.toString(),
- "-addmods", "ALL-MODULE-PATH",
- "-cp", CLASSES_DIR.toString(),
- MAIN_CLASS)
+ = executeTestJava("-mp", MODS1_DIR.toString(),
+ "-addmods", "ALL-SYSTEM",
+ "-m", TEST_MID,
+ "java.sql.Connection",
+ "javax.annotation.Generated")
.outputTo(System.out)
.errorTo(System.out)
.getExitValue();
assertTrue(exitValue == 0);
-
}
/**
- * Run application on class path that makes use of module on the
- * application module path. Does not use -addmods and so will
- * fail at run-time.
+ * Run test on class path to load a type in a module on the application
+ * module path, uses {@code -addmods logger}.
*/
- public void testRunMissingAddMods() throws Exception {
+ public void testRunWithAddMods() throws Exception {
- // java -mp mods -cp classes app.Main
+ // java -mp mods -addmods logger -cp classes test.Main
+ String classpath = MODS1_DIR.resolve(TEST_MODULE).toString();
+ String modulepath = MODS2_DIR.toString();
int exitValue
- = executeTestJava("-mp", MODS_DIR.toString(),
- "-cp", CLASSES_DIR.toString(),
- MAIN_CLASS)
+ = executeTestJava("-mp", modulepath,
+ "-addmods", LOGGER_MODULE,
+ "-cp", classpath,
+ TEST_MAIN_CLASS,
+ "logger.Logger")
.outputTo(System.out)
.errorTo(System.out)
.getExitValue();
- // CNFE or other error/exception
- assertTrue(exitValue != 0);
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Run application on class path that makes use of module on the
+ * application module path. Does not use -addmods and so should
+ * fail at run-time.
+ */
+ public void testRunMissingAddMods() throws Exception {
+
+ // java -mp mods -cp classes test.Main
+ String classpath = MODS1_DIR.resolve(TEST_MODULE).toString();
+ String modulepath = MODS1_DIR.toString();
+ int exitValue
+ = executeTestJava("-mp", modulepath,
+ "-cp", classpath,
+ TEST_MAIN_CLASS,
+ "logger.Logger")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .shouldContain("ClassNotFoundException")
+ .getExitValue();
+
+ assertTrue(exitValue != 0);
+ }
+
+ /**
+ * Run test on class path to load a type in a module on the application
+ * module path, uses {@code -addmods ALL-MODULE-PATH}.
+ */
+ public void testAddAllModulePath() throws Exception {
+
+ // java -mp mods -addmods ALL-MODULE-PATH -cp classes test.Main
+ String classpath = MODS1_DIR.resolve(TEST_MODULE).toString();
+ String modulepath = MODS1_DIR.toString();
+ int exitValue
+ = executeTestJava("-mp", modulepath,
+ "-addmods", "ALL-MODULE-PATH",
+ "-cp", classpath,
+ TEST_MAIN_CLASS)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue();
+
+ assertTrue(exitValue == 0);
+ }
+
+
+ /**
+ * Test {@code -addmods ALL-MODULE-PATH} without {@code -modulepath}.
+ */
+ public void testAddAllModulePathWithNoModulePath() throws Exception {
+
+ // java -addmods ALL-MODULE-PATH -version
+ int exitValue
+ = executeTestJava("-addmods", "ALL-MODULE-PATH",
+ "-version")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue();
+
+ assertTrue(exitValue == 0);
}
@@ -169,18 +228,17 @@
*/
public void testRunWithBadAddMods() throws Exception {
- // java -mp mods -addmods,DoesNotExist lib -cp classes app.Main
+ // java -mp mods -addmods DoesNotExist -m test ...
int exitValue
- = executeTestJava("-mp", MODS_DIR.toString(),
- "-addmods", LIB_MODULE + ",DoesNotExist",
- "-cp", CLASSES_DIR.toString(),
- MAIN_CLASS)
+ = executeTestJava("-mp", MODS1_DIR.toString(),
+ "-addmods", "DoesNotExist",
+ "-m", TEST_MID)
.outputTo(System.out)
.errorTo(System.out)
+ .shouldContain("DoesNotExist")
.getExitValue();
assertTrue(exitValue != 0);
-
}
}
--- a/jdk/test/tools/launcher/modules/addmods/src/app/Main.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 app;
-
-import jdk.lib.Util;
-
-public class Main {
- public static void main(String[] args) {
- Object obj = Util.makeObject();
- }
-}
--- a/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.lib;
-
-public class Util {
- private Util() { }
-
- public static Object makeObject() {
- return new Object();
- }
-}
--- a/jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-module lib {
- exports jdk.lib;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/addmods/src/logger/logger/Logger.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * 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 logger;
+
+/**
+ * No-op user module for use by the {@code java -addmods} tests.
+ */
+public class Logger {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/addmods/src/logger/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+
+module logger { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/addmods/src/test/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+
+module test { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/addmods/src/test/test/Main.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test;
+
+/**
+ * Invoked by tests for the {@code java -addmods} option to check that types
+ * are visible.
+ */
+public class Main {
+ public static void main(String[] args) throws Exception {
+ for (String cn : args) {
+ Class<?> c = Class.forName(cn);
+ System.out.println("Loaded: " + c);
+ }
+ }
+}
--- a/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,7 @@
* @test
* @library /lib/testlibrary
* @modules jdk.compiler
- * @build AddReadsTest CompilerUtils jdk.testlibrary.*
+ * @build AddReadsTest CompilerUtils JarUtils jdk.testlibrary.*
* @run testng AddReadsTest
* @summary Basic tests for java -XaddReads
*/
--- a/jdk/test/tools/launcher/modules/patch/PatchTest.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/launcher/modules/patch/PatchTest.java Fri May 06 06:23:30 2016 -0700
@@ -25,7 +25,7 @@
* @test
* @library /lib/testlibrary
* @modules jdk.compiler
- * @build PatchTest CompilerUtils jdk.testlibrary.*
+ * @build PatchTest CompilerUtils JarUtils jdk.testlibrary.*
* @run testng PatchTest
* @summary Basic test for -Xpatch
*/
@@ -72,6 +72,9 @@
private static final Path SRC2_DIR = Paths.get(TEST_SRC, "src2");
private static final Path PATCHES2_DIR = Paths.get("patches2");
+ // destination directory for patches packaged as JAR files
+ private static final Path PATCHES_DIR = Paths.get("patches");
+
// the classes overridden or added with -Xpatch
private static final String[] CLASSES = {
@@ -95,7 +98,7 @@
@BeforeTest
- public void compile() throws Exception {
+ public void setup() throws Exception {
// javac -d mods/test src/test/**
boolean compiled= CompilerUtils.compile(SRC_DIR.resolve("test"),
@@ -103,36 +106,40 @@
assertTrue(compiled, "classes did not compile");
// javac -Xmodule:$MODULE -d patches1/$MODULE patches1/$MODULE/**
+ // jar cf patches/$MODULE-1.jar -C patches1/$MODULE .
for (Path src : Files.newDirectoryStream(SRC1_DIR)) {
Path output = PATCHES1_DIR.resolve(src.getFileName());
String mn = src.getFileName().toString();
compiled = CompilerUtils.compile(src, output, "-Xmodule:" + mn);
assertTrue(compiled, "classes did not compile");
+ JarUtils.createJarFile(PATCHES_DIR.resolve(mn + "-1.jar"), output);
}
// javac -Xmodule:$MODULE -d patches2/$MODULE patches2/$MODULE/**
+ // jar cf patches/$MODULE-2.jar -C patches2/$MODULE .
for (Path src : Files.newDirectoryStream(SRC2_DIR)) {
Path output = PATCHES2_DIR.resolve(src.getFileName());
String mn = src.getFileName().toString();
compiled = CompilerUtils.compile(src, output, "-Xmodule:" + mn);
assertTrue(compiled, "classes did not compile");
+ JarUtils.createJarFile(PATCHES_DIR.resolve(mn + "-2.jar"), output);
}
}
/**
- * Run the test with -Xpatch
+ * Run test with patches to java.base, jdk.naming.dns and jdk.compiler
*/
- public void testRunWithXPatch() throws Exception {
-
- // value for -Xpatch
- String patchPath = PATCHES1_DIR + File.pathSeparator + PATCHES2_DIR;
-
+ void runTest(String basePatches, String dnsPatches, String compilerPatches)
+ throws Exception
+ {
// the argument to the test is the list of classes overridden or added
String arg = Stream.of(CLASSES).collect(Collectors.joining(","));
int exitValue
- = executeTestJava("-Xpatch:" + patchPath,
+ = executeTestJava("-Xpatch:java.base=" + basePatches,
+ "-Xpatch:jdk.naming.dns=" + dnsPatches,
+ "-Xpatch:jdk.compiler=" + compilerPatches,
"-XaddExports:java.base/java.lang2=test",
"-XaddExports:jdk.naming.dns/com.sun.jndi.dns=test",
"-XaddExports:jdk.naming.dns/com.sun.jndi.dns2=test",
@@ -145,6 +152,44 @@
.getExitValue();
assertTrue(exitValue == 0);
+ }
+
+
+ /**
+ * Run test with -Xpatch and exploded patches
+ */
+ public void testWithExplodedPatches() throws Exception {
+
+ // patches1/java.base:patches2/java.base
+ String basePatches = PATCHES1_DIR.resolve("java.base")
+ + File.pathSeparator + PATCHES2_DIR.resolve("java.base");
+
+ String dnsPatches = PATCHES1_DIR.resolve("jdk.naming.dns")
+ + File.pathSeparator + PATCHES2_DIR.resolve("jdk.naming.dns");
+
+ String compilerPatches = PATCHES1_DIR.resolve("jdk.compiler")
+ + File.pathSeparator + PATCHES2_DIR.resolve("jdk.compiler");
+
+ runTest(basePatches, dnsPatches, compilerPatches);
+ }
+
+
+ /**
+ * Run test with -Xpatch and patches in JAR files
+ */
+ public void testWitJarPatches() throws Exception {
+
+ // patches/java.base-1.jar:patches/java-base-2.jar
+ String basePatches = PATCHES_DIR.resolve("java.base-1.jar")
+ + File.pathSeparator + PATCHES_DIR.resolve("java.base-2.jar");
+
+ String dnsPatches = PATCHES_DIR.resolve("jdk.naming.dns-1.jar")
+ + File.pathSeparator + PATCHES_DIR.resolve("jdk.naming.dns-2.jar");
+
+ String compilerPatches = PATCHES_DIR.resolve("jdk.compiler-1.jar")
+ + File.pathSeparator + PATCHES_DIR.resolve("jdk.compiler-2.jar");
+
+ runTest(basePatches, dnsPatches, compilerPatches);
}
--- a/jdk/test/tools/lib/tests/JImageGenerator.java Fri May 06 11:47:45 2016 +0300
+++ b/jdk/test/tools/lib/tests/JImageGenerator.java Fri May 06 06:23:30 2016 -0700
@@ -113,7 +113,7 @@
private static final String CMDS_OPTION = "--cmds";
private static final String CONFIG_OPTION = "--config";
- private static final String HASH_DEPENDENCIES_OPTION = "--hash-dependencies";
+ private static final String HASH_MODULES_OPTION = "--hash-modules";
private static final String LIBS_OPTION = "--libs";
private static final String MODULE_VERSION_OPTION = "--module-version";
@@ -347,7 +347,7 @@
private final List<Path> jmods = new ArrayList<>();
private final List<String> options = new ArrayList<>();
private Path output;
- private String hashDependencies;
+ private String hashModules;
private String mainClass;
private String moduleVersion;
@@ -356,8 +356,8 @@
return this;
}
- public JModTask hashDependencies(String hash) {
- this.hashDependencies = hash;
+ public JModTask hashModules(String hash) {
+ this.hashModules = hash;
return this;
}
@@ -430,9 +430,9 @@
options.add(CONFIG_OPTION);
options.add(toPath(config));
}
- if (hashDependencies != null) {
- options.add(HASH_DEPENDENCIES_OPTION);
- options.add(hashDependencies);
+ if (hashModules != null) {
+ options.add(HASH_MODULES_OPTION);
+ options.add(hashModules);
}
if (mainClass != null) {
options.add(MAIN_CLASS_OPTION);
--- a/langtools/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/langtools/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -358,3 +358,4 @@
4e87682893e662421af10a62d29ae822ce0fea04 jdk-9+113
cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114
31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115
+3e3553ee39d9e081573bc7c88a252214a3152763 jdk-9+116
--- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java Fri May 06 06:23:30 2016 -0700
@@ -123,7 +123,9 @@
private static <T> T getSystemTool(Class<T> clazz, String moduleName, String className) {
if (useLegacy) {
try {
- return Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance();
+ @SuppressWarnings("deprecation")
+ T result = Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance();
+ return result;
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Fri May 06 06:23:30 2016 -0700
@@ -698,7 +698,7 @@
*/
public boolean packageExists(ModuleSymbol msym, Name fullname) {
Assert.checkNonNull(msym);
- return enterPackage(msym, fullname).exists();
+ return lookupPackage(msym, fullname).exists();
}
/** Make a package, given its fully qualified name.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri May 06 06:23:30 2016 -0700
@@ -53,10 +53,6 @@
public class MemberEnter extends JCTree.Visitor {
protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<>();
- /** A switch to determine whether we check for package/class conflicts
- */
- final static boolean checkClash = true;
-
private final Enter enter;
private final Log log;
private final Check chk;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri May 06 06:23:30 2016 -0700
@@ -826,7 +826,7 @@
}
public void visitClass(Attribute.Class clazz) {
databuf.appendByte('c');
- databuf.appendChar(pool.put(typeSig(clazz.classType)));
+ databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType))));
}
public void visitCompound(Attribute.Compound compound) {
databuf.appendByte('@');
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Fri May 06 06:23:30 2016 -0700
@@ -1086,17 +1086,19 @@
genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
code.resolve(loopEnv.info.cont);
genStats(step, loopEnv);
- CondItem c;
- if (cond != null) {
- code.statBegin(cond.pos);
+ if (code.isAlive()) {
+ CondItem c;
+ if (cond != null) {
+ code.statBegin(cond.pos);
+ Assert.check(code.state.stacksize == 0);
+ c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
+ } else {
+ c = items.makeCondItem(goto_);
+ }
+ code.resolve(c.jumpTrue(), startpc);
Assert.check(code.state.stacksize == 0);
- c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
- } else {
- c = items.makeCondItem(goto_);
+ code.resolve(c.falseJumps);
}
- code.resolve(c.jumpTrue(), startpc);
- Assert.check(code.state.stacksize == 0);
- code.resolve(c.falseJumps);
}
Chain exit = loopEnv.info.exit;
if (exit != null) {
@@ -1647,6 +1649,7 @@
public void visitConditional(JCConditional tree) {
Chain thenExit = null;
+ code.statBegin(tree.cond.pos);
CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER);
Chain elseChain = c.jumpFalse();
if (!c.isFalse()) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri May 06 06:23:30 2016 -0700
@@ -282,6 +282,7 @@
if (options.isSet(XPRINT)) {
try {
+ @SuppressWarnings("deprecation")
Processor processor = PrintingProcessor.class.newInstance();
processorIterator = List.of(processor).iterator();
} catch (Throwable t) {
@@ -549,8 +550,9 @@
try {
Class<?> processorClass = processorCL.loadClass(processorName);
ensureReadable(processorClass);
- processor =
- (Processor) (processorClass.newInstance());
+ @SuppressWarnings("deprecation")
+ Object tmp = processorClass.newInstance();
+ processor = (Processor) tmp;
} catch (ClassNotFoundException cnfe) {
log.error("proc.processor.not.found", processorName);
return false;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -151,6 +151,7 @@
// Construct transformer
try {
Class<?> trCls = Class.forName(classname);
+ @SuppressWarnings("deprecation")
Transformer transformer = (Transformer) trCls.newInstance();
transformer.setExtra(extra);
helper.addTransformer(suffix, transformer);
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Fri May 06 06:23:30 2016 -0700
@@ -1,4 +1,4 @@
-doclet.build_version=Standard Doclet version {0}
+doclet.build_version=Standard Doclet (Old) version {0}
doclet.Contents=Contents
doclet.Overview=Overview
doclet.Window_Overview=Overview List
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java Fri May 06 06:23:30 2016 -0700
@@ -242,7 +242,6 @@
}
customTagClass = tagClassLoader.loadClass(classname);
- ensureReadable(customTagClass);
Method meth = customTagClass.getMethod("register",
Map.class);
@@ -270,27 +269,6 @@
}
/**
- * Ensures that the module of the given class is readable to this
- * module.
- * @param targetClass class in module to be made readable
- */
- private void ensureReadable(Class<?> targetClass) {
- try {
- Method getModuleMethod = Class.class.getMethod("getModule");
- Object thisModule = getModuleMethod.invoke(this.getClass());
- Object targetModule = getModuleMethod.invoke(targetClass);
-
- Class<?> moduleClass = getModuleMethod.getReturnType();
- Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
- addReadsMethod.invoke(thisModule, targetModule);
- } catch (NoSuchMethodException e) {
- // ignore
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
-
- /**
* Export javadoc internal API to the unnamed module for a classloader.
* This is to support continued use of existing non-standard doclets that
* use the internal toolkit API and related classes.
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java Fri May 06 06:23:30 2016 -0700
@@ -102,7 +102,6 @@
this.apiMode = apiMode;
this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
- ensureReadable(docletClass);
// this may not be soon enough if the class has already been loaded
if (exportInternalAPI) {
exportInternalAPI(docletClass.getClassLoader());
@@ -149,8 +148,6 @@
messager.exit();
}
docletClass = dc;
-
- ensureReadable(docletClass);
}
/*
@@ -362,27 +359,6 @@
}
/**
- * Ensures that the module of the given class is readable to this
- * module.
- * @param targetClass class in module to be made readable
- */
- private void ensureReadable(Class<?> targetClass) {
- try {
- Method getModuleMethod = Class.class.getMethod("getModule");
- Object thisModule = getModuleMethod.invoke(this.getClass());
- Object targetModule = getModuleMethod.invoke(targetClass);
-
- Class<?> moduleClass = getModuleMethod.getReturnType();
- Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
- addReadsMethod.invoke(thisModule, targetModule);
- } catch (NoSuchMethodException e) {
- // ignore
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
-
- /**
* Export javadoc internal API to the unnamed module for a classloader.
* This is to support continued use of existing non-standard doclets that
* use the internal toolkit API and related classes.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java Fri May 06 06:23:30 2016 -0700
@@ -168,6 +168,21 @@
}
/**
+ * {@inheritDoc}
+ */
+ public void addModuleDescription(Content moduleContentTree) {
+ if (!utils.getBody(mdle).isEmpty()) {
+ Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree;
+ tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION);
+ tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION));
+ addInlineComment(mdle, tree);
+ if (configuration.allowTag(HtmlTag.SECTION)) {
+ moduleContentTree.addContent(tree);
+ }
+ }
+ }
+
+ /**
* Adds list of packages in the package summary table. Generate link to each package.
*
* @param packages Packages to which link is to be generated
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java Fri May 06 06:23:30 2016 -0700
@@ -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
@@ -53,6 +53,7 @@
METHOD_DETAIL("method.detail"),
METHODS_INHERITANCE("methods.inherited.from.class."),
METHOD_SUMMARY("method.summary"),
+ MODULE_DESCRIPTION("module.description"),
NAVBAR_BOTTOM("navbar.bottom"),
NAVBAR_BOTTOM_FIRSTROW("navbar.bottom.firstrow"),
NAVBAR_TOP("navbar.top"),
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -64,6 +64,12 @@
new Comment("======== END OF BOTTOM NAVBAR =======");
/**
+ * Marker to identify start of module description.
+ */
+ public static final Content START_OF_MODULE_DESCRIPTION =
+ new Comment("============ MODULE DESCRIPTION ===========");
+
+ /**
* Marker to identify start of class data.
*/
public static final Content START_OF_CLASS_DATA =
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties Fri May 06 06:23:30 2016 -0700
@@ -1,4 +1,4 @@
-doclet.build_version=Standard Doclet (Next) version {0}
+doclet.build_version=Standard Doclet version {0}
doclet.Contents=Contents
doclet.Overview=Overview
doclet.Window_Overview=Overview List
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java Fri May 06 06:23:30 2016 -0700
@@ -74,6 +74,14 @@
public abstract Content getSummaryTree(Content summaryContentTree);
/**
+ * Adds the module description.
+ *
+ * @param moduleContentTree the content tree to which the module description
+ * will be added
+ */
+ public abstract void addModuleDescription(Content moduleContentTree);
+
+ /**
* Adds the table of packages to the documentation tree.
*
* @param packages the set of packages that should be added.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -185,4 +185,17 @@
packageTableSummary, summaryContentTree);
}
}
+
+ /**
+ * Build the description for the module.
+ *
+ * @param node the XML element that specifies which components to document
+ * @param moduleContentTree the tree to which the module description will
+ * be added
+ */
+ public void buildModuleDescription(XMLNode node, Content moduleContentTree) {
+ if (!configuration.nocomment) {
+ moduleWriter.addModuleDescription(moduleContentTree);
+ }
+ }
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml Fri May 06 06:23:30 2016 -0700
@@ -30,6 +30,7 @@
<ModuleDoc>
<Content>
+ <ModuleDescription/>
<Summary>
<PackageSummary/>
</Summary>
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Fri May 06 06:23:30 2016 -0700
@@ -246,7 +246,7 @@
}
tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
Class<?> customTagClass = tagClassLoader.loadClass(classname);
- ensureReadable(customTagClass);
+ @SuppressWarnings("deprecation")
Object instance = customTagClass.newInstance();
Taglet newLegacy = new UserTaglet((jdk.javadoc.doclet.taglet.Taglet)instance);
String tname = newLegacy.getName();
@@ -262,27 +262,6 @@
}
/**
- * Ensures that the module of the given class is readable to this
- * module.
- * @param targetClass class in module to be made readable
- */
- private void ensureReadable(Class<?> targetClass) {
- try {
- Method getModuleMethod = Class.class.getMethod("getModule");
- Object thisModule = getModuleMethod.invoke(this.getClass());
- Object targetModule = getModuleMethod.invoke(targetClass);
-
- Class<?> moduleClass = getModuleMethod.getReturnType();
- Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
- addReadsMethod.invoke(thisModule, targetModule);
- } catch (NoSuchMethodException e) {
- // ignore
- } catch (Exception e) {
- throw new InternalError(e.toString());
- }
- }
-
- /**
* Add a new <code>SimpleTaglet</code>. If this tag already exists
* and the header passed as an argument is null, move tag to the back of the
* list. If this tag already exists and the header passed as an argument is
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -73,6 +73,7 @@
private final Configuration configuration;
private final Utils utils;
+ private final Comparator<Element> comparator;
/**
* Constructor. Build the index map.
@@ -106,6 +107,9 @@
this.classesOnly = classesOnly;
this.javafx = configuration.javafx;
this.indexmap = new TreeMap<>();
+ comparator = classesOnly
+ ? utils.makeAllClassesComparator()
+ : utils.makeIndexUseComparator();
buildIndexMap(configuration.root);
}
@@ -175,7 +179,7 @@
Character.toUpperCase(name.charAt(0));
Character unicode = ch;
SortedSet<Element> list = indexmap.computeIfAbsent(unicode,
- c -> new TreeSet<>(utils.makeIndexUseComparator()));
+ c -> new TreeSet<>(comparator));
list.add(element);
}
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Fri May 06 06:23:30 2016 -0700
@@ -1628,6 +1628,7 @@
/**
* Comparator for ModuleElements, simply compares the fully qualified names
+ * @return a Comparator
*/
public Comparator<Element> makeModuleComparator() {
return new Utils.ElementComparator<Element>() {
@@ -1639,7 +1640,28 @@
}
/**
- * Comparator for PackageElements, simply compares the fully qualified names
+ * Returns a Comparator for all classes, compares the simple names of
+ * TypeElement, if equal then the fully qualified names.
+ *
+ * @return Comparator
+ */
+ public Comparator<Element> makeAllClassesComparator() {
+ return new Utils.ElementComparator<Element>() {
+ @Override
+ public int compare(Element e1, Element e2) {
+ int result = compareNames(e1, e2);
+ if (result == 0)
+ result = compareFullyQualifiedNames(e1, e2);
+
+ return result;
+ }
+ };
+ }
+
+ /**
+ * Returns a Comparator for packages, by comparing the fully qualified names.
+ *
+ * @return a Comparator
*/
public Comparator<Element> makePackageComparator() {
return new Utils.ElementComparator<Element>() {
@@ -1650,6 +1672,10 @@
};
}
+ /**
+ * Returns a Comparator for SerialFieldTree.
+ * @return a Comparator
+ */
public Comparator<SerialFieldTree> makeSerialFieldTreeComparator() {
return (SerialFieldTree o1, SerialFieldTree o2) -> {
String s1 = o1.getName().toString();
@@ -1659,18 +1685,19 @@
}
/**
- * Comparator for General Purpose
- * @return a ElementComparatorForClassUse
+ * Returns a general purpose comparator.
+ * @return a Comparator
*/
public Comparator<Element> makeGeneralPurposeComparator() {
return makeClassUseComparator();
}
/**
- * A Comparator for Overrides and Implements use used on ExecutableElements
- * compares the name first, then compares the SimpleName of the enclosing
- * class and the FullyQualifiedName of the enclosing class.
- * @return
+ * Returns a Comparator for overrides and implements,
+ * used primarily on methods, compares the name first,
+ * then compares the simple names of the enclosing
+ * TypeElement and the fully qualified name of the enclosing TypeElement.
+ * @return a Comparator
*/
public Comparator<Element> makeOverrideUseComparator() {
return new Utils.ElementComparator<Element>() {
@@ -1696,21 +1723,24 @@
}
/**
- * A comparator for index file presentations, and are sorted as follows:
+ * Returns a Comparator for index file presentations, and are sorted as follows.
+ * If comparing packages then simply compare the qualified names, otherwise
* 1. sort on simple names of entities
* 2. if equal, then compare the ElementKind ex: Package, Interface etc.
* 3a. if equal and if the type is of ExecutableElement(Constructor, Methods),
* a case insensitive comparison of parameter the type signatures
* 3b. if equal, case sensitive comparison of the type signatures
* 4. finally, if equal, compare the FQNs of the entities
+ * Iff comparing packages then simply sort on qualified names.
* @return a comparator for index file use
*/
public Comparator<Element> makeIndexUseComparator() {
return new Utils.ElementComparator<Element>() {
/**
- * Compare two given elements, first sort on names, then on the kinds,
- * then on the parameters only if the type is an instance of ExecutableElement,
- * the parameters are compared and finally the fully qualified names.
+ * Compare two given elements, if comparing two packages, return the
+ * comparison of FullyQualifiedName, first sort on names, then on the
+ * kinds, then on the parameters only if the type is an ExecutableElement,
+ * the parameters are compared and finally the qualified names.
*
* @param e1 - an element.
* @param e2 - an element.
@@ -1719,10 +1749,7 @@
*/
@Override
public int compare(Element e1, Element e2) {
- int result = compareElementTypeKinds(e1, e2);
- if (result != 0) {
- return result;
- }
+ int result = 0;
if (isPackage(e1) && isPackage(e2)) {
return compareFullyQualifiedNames(e1, e2);
}
@@ -1730,6 +1757,10 @@
if (result != 0) {
return result;
}
+ result = compareElementTypeKinds(e1, e2);
+ if (result != 0) {
+ return result;
+ }
if (hasParameters(e1)) {
List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java Fri May 06 06:23:30 2016 -0700
@@ -550,7 +550,7 @@
// Messager should be replaced by a more general
// compilation environment. This can probably
// subsume DocEnv as well.
- messager.exit();
+ throw new Messager.ExitJavadoc();
}
/**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java Fri May 06 06:23:30 2016 -0700
@@ -59,13 +59,6 @@
* @return The return code.
*/
public static int execute(String... args) {
- // NOTE: the following should be removed when the old doclet
- // is removed.
- if (args != null && args.length > 0 && "-Xold".equals(args[0])) {
- String[] nargs = new String[args.length - 1];
- System.arraycopy(args, 1, nargs, 0, nargs.length);
- return com.sun.tools.javadoc.Main.execute(nargs);
- }
Start jdoc = new Start();
return jdoc.begin(args);
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -139,7 +139,7 @@
}
}
- public class ExitJavadoc extends Error {
+ public static class ExitJavadoc extends Error {
private static final long serialVersionUID = 0;
}
@@ -416,15 +416,6 @@
}
}
- /**
- * Force program exit, e.g., from a fatal error.
- * <p>
- * TODO: This method does not really belong here.
- */
- public void exit() {
- throw new ExitJavadoc();
- }
-
private void report(DiagnosticType type, String pos, String msg) {
switch (type) {
case ERROR:
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java Fri May 06 06:23:30 2016 -0700
@@ -66,6 +66,7 @@
import jdk.javadoc.doclet.DocletEnvironment;
import static com.sun.tools.javac.main.Option.*;
+
/**
* Main program of Javadoc.
* Previously named "Main".
@@ -79,6 +80,12 @@
* @author Neal Gafter (rewrite)
*/
public class Start extends ToolOption.Helper {
+
+ private static final Class<?> OldStdDoclet =
+ com.sun.tools.doclets.standard.Standard.class;
+
+ private static final Class<?> StdDoclet =
+ jdk.javadoc.internal.doclets.standard.Standard.class;
/** Context for this invocation. */
private final Context context;
@@ -193,18 +200,26 @@
if (foot != null)
messager.notice(foot);
- if (exit) exit();
+ if (exit)
+ throw new Messager.ExitJavadoc();
}
+
/**
- * Exit
- */
- private void exit() {
- messager.exit();
- }
-
- /**
- * Main program - external wrapper
+ * Main program - external wrapper. In order to maintain backward
+ * CLI compatibility, we dispatch to the old tool or the old doclet's
+ * Start mechanism, based on the options present on the command line
+ * with the following precedence:
+ * 1. presence of -Xold, dispatch to old tool
+ * 2. doclet variant, if old, dispatch to old Start
+ * 3. taglet variant, if old, dispatch to old Start
+ *
+ * Thus the presence of -Xold switches the tool, soon after command files
+ * if any, are expanded, this is performed here, noting that the messager
+ * is available at this point in time.
+ * The doclet/taglet tests are performed in the begin method, further on,
+ * this is to minimize argument processing and most importantly the impact
+ * of class loader creation, needed to detect the doclet/taglet class variants.
*/
int begin(String... argv) {
// Preprocess @file arguments
@@ -212,14 +227,18 @@
argv = CommandLine.parse(argv);
} catch (FileNotFoundException e) {
messager.error("main.cant.read", e.getMessage());
- exit();
+ throw new Messager.ExitJavadoc();
} catch (IOException e) {
e.printStackTrace(System.err);
- exit();
+ throw new Messager.ExitJavadoc();
}
- List<String> argList = Arrays.asList(argv);
- boolean ok = begin(argList, Collections.<JavaFileObject> emptySet());
+ if (argv.length > 0 && "-Xold".equals(argv[0])) {
+ messager.warning("main.legacy_api");
+ String[] nargv = Arrays.copyOfRange(argv, 1, argv.length);
+ return com.sun.tools.javadoc.Main.execute(nargv);
+ }
+ boolean ok = begin(Arrays.asList(argv), Collections.<JavaFileObject> emptySet());
return ok ? 0 : 1;
}
@@ -231,11 +250,11 @@
List<String> opts = new ArrayList<>();
for (String opt: options)
opts.add(opt);
+
return begin(opts, fileObjects);
}
private boolean begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
-
fileManager = context.get(JavaFileManager.class);
if (fileManager == null) {
JavacFileManager.preRegister(context);
@@ -244,20 +263,21 @@
((BaseFileManager) fileManager).autoClose = true;
}
}
- // locale and doclet needs to be determined first
+ // locale, doclet and maybe taglet, needs to be determined first
docletClass = preProcess(fileManager, options);
-
if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
// no need to dispatch to old, safe to init now
initMessager();
messager.setLocale(locale);
try {
- doclet = (Doclet) docletClass.newInstance();
+ @SuppressWarnings("deprecation")
+ Object o = docletClass.newInstance();
+ doclet = (Doclet) o;
} catch (InstantiationException | IllegalAccessException exc) {
exc.printStackTrace();
if (!apiMode) {
error("main.could_not_instantiate_class", docletClass);
- messager.exit();
+ throw new Messager.ExitJavadoc();
}
throw new ClientCodeException(exc);
}
@@ -267,6 +287,7 @@
= new com.sun.tools.javadoc.Start(context);
return ostart.begin(docletClass, options, fileObjects);
}
+ warn("main.legacy_api");
String[] array = options.toArray(new String[options.size()]);
return com.sun.tools.javadoc.Main.execute(array) == 0;
}
@@ -312,27 +333,6 @@
}
/**
- * Ensures that the module of the given class is readable to this
- * module.
- * @param targetClass class in module to be made readable
- */
- private void ensureReadable(Class<?> targetClass) {
- try {
- Method getModuleMethod = Class.class.getMethod("getModule");
- Object thisModule = getModuleMethod.invoke(this.getClass());
- Object targetModule = getModuleMethod.invoke(targetClass);
-
- Class<?> moduleClass = getModuleMethod.getReturnType();
- Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
- addReadsMethod.invoke(thisModule, targetModule);
- } catch (NoSuchMethodException e) {
- // ignore
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
-
- /**
* Main program - internal
*/
private boolean parseAndExecute(List<String> argList,
@@ -459,6 +459,11 @@
String userDocletPath = null;
String userDocletName = null;
+ // taglet specifying arguments, since tagletpath is a doclet
+ // functionality, assume they are repeated and inspect all.
+ List<File> userTagletPath = new ArrayList<>();
+ List<String> userTagletNames = new ArrayList<>();
+
// Step 1: loop through the args, set locale early on, if found.
for (int i = 0 ; i < argv.size() ; i++) {
String arg = argv.get(i);
@@ -470,7 +475,7 @@
oneArg(argv, i++);
if (userDocletName != null) {
usageError("main.more_than_one_doclet_specified_0_and_1",
- userDocletName, argv.get(i));
+ userDocletName, argv.get(i));
}
if (docletName != null) {
usageError("main.more_than_one_doclet_specified_0_and_1",
@@ -484,13 +489,20 @@
} else {
userDocletPath += File.pathSeparator + argv.get(i);
}
+ } else if ("-taglet".equals(arg)) {
+ userTagletNames.add(argv.get(i + 1));
+ } else if ("-tagletpath".equals(arg)) {
+ for (String pathname : argv.get(i + 1).split(File.pathSeparator)) {
+ userTagletPath.add(new File(pathname));
+ }
}
}
- // Step 2: a doclet has already been provided,
- // nothing more to do.
+
+ // Step 2: a doclet is provided, nothing more to do.
if (docletClass != null) {
return docletClass;
}
+
// Step 3: doclet name specified ? if so find a ClassLoader,
// and load it.
if (userDocletName != null) {
@@ -506,38 +518,78 @@
try {
((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
} catch (IOException ioe) {
- panic("main.doclet_no_classloader_found", ioe);
- return null; // keep compiler happy
+ error("main.doclet_could_not_set_location", paths);
+ throw new Messager.ExitJavadoc();
}
}
cl = fileManager.getClassLoader(DOCLET_PATH);
if (cl == null) {
// despite doclet specified on cmdline no classloader found!
- panic("main.doclet_no_classloader_found", userDocletName);
- return null; // keep compiler happy
- }
- try {
- Class<?> klass = cl.loadClass(userDocletName);
- ensureReadable(klass);
- return klass;
- } catch (ClassNotFoundException cnfe) {
- panic("main.doclet_class_not_found", userDocletName);
- return null; // keep compiler happy
+ error("main.doclet_no_classloader_found", userDocletName);
+ throw new Messager.ExitJavadoc();
}
}
+ try {
+ Class<?> klass = cl.loadClass(userDocletName);
+ return klass;
+ } catch (ClassNotFoundException cnfe) {
+ error("main.doclet_class_not_found", userDocletName);
+ throw new Messager.ExitJavadoc();
+ }
}
- // Step 4: we have a doclet, try loading it, otherwise
- // return back the standard doclet
+
+ // Step 4: we have a doclet, try loading it
if (docletName != null) {
try {
return Class.forName(docletName, true, getClass().getClassLoader());
} catch (ClassNotFoundException cnfe) {
- panic("main.doclet_class_not_found", userDocletName);
- return null; // happy compiler, should not happen
+ error("main.doclet_class_not_found", userDocletName);
+ throw new Messager.ExitJavadoc();
}
- } else {
- return jdk.javadoc.internal.doclets.standard.Standard.class;
+ }
+
+ // Step 5: we don't have a doclet specified, do we have taglets ?
+ if (!userTagletNames.isEmpty() && hasOldTaglet(userTagletNames, userTagletPath)) {
+ // found a bogey, return the old doclet
+ return OldStdDoclet;
}
+
+ // finally
+ return StdDoclet;
+ }
+
+ /*
+ * This method returns true iff it finds a legacy taglet, but for
+ * all other conditions including errors it returns false, allowing
+ * nature to take its own course.
+ */
+ private boolean hasOldTaglet(List<String> tagletNames, List<File> tagletPaths) {
+ if (!fileManager.hasLocation(TAGLET_PATH)) {
+ try {
+ ((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, tagletPaths);
+ } catch (IOException ioe) {
+ error("main.doclet_could_not_set_location", tagletPaths);
+ throw new Messager.ExitJavadoc();
+ }
+ }
+ ClassLoader cl = fileManager.getClassLoader(TAGLET_PATH);
+ if (cl == null) {
+ // no classloader found!
+ error("main.doclet_no_classloader_found", tagletNames.get(0));
+ throw new Messager.ExitJavadoc();
+ }
+ for (String tagletName : tagletNames) {
+ try {
+ Class<?> klass = cl.loadClass(tagletName);
+ if (com.sun.tools.doclets.Taglet.class.isAssignableFrom(klass)) {
+ return true;
+ }
+ } catch (ClassNotFoundException cnfe) {
+ error("main.doclet_class_not_found", tagletName);
+ throw new Messager.ExitJavadoc();
+ }
+ }
+ return false;
}
private void parseArgs(List<String> args, List<String> javaNames) {
@@ -595,14 +647,12 @@
usage(true);
}
- // a terminal call, will not return
- void panic(String key, Object... args) {
- error(key, args);
- messager.exit();
+ void error(String key, Object... args) {
+ messager.error(key, args);
}
- void error(String key, Object... args) {
- messager.error(key, args);
+ void warn(String key, Object... args) {
+ messager.warning(key, args);
}
/**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties Fri May 06 06:23:30 2016 -0700
@@ -73,7 +73,8 @@
\ given module. <other-module> may be ALL-UNNAMED to require\n\
\ the unnamed module.\n\
\ -Xmodule:<module-name> Specify a module to which the classes being compiled belong.\n\
-\ -Xpatch:<path> Specify location of module class files to patch\n
+\ -Xpatch:<path> Specify location of module class files to patch\n\
+\ -Xold Invoke the legacy javadoc tool\n
main.Xusage.foot=\
These options are non-standard and subject to change without notice.
@@ -96,6 +97,7 @@
such as -J-Xmx32m.
main.done_in=[done in {0} ms]
main.more_than_one_doclet_specified_0_and_1=More than one doclet specified ({0} and {1}).
+main.doclet_could_not_set_location=Could not set location for {0}
main.doclet_no_classloader_found=Could not obtain classloader to load {0}
main.could_not_instantiate_class=Could not instantiate class {0}
main.doclet_class_not_found=Cannot find doclet class {0}
@@ -109,10 +111,15 @@
main.unsupported.release.version=release version {0} not supported
main.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager.
main.unknown.error=an unknown error has occurred
+main.legacy_api=The old Doclet and Taglet APIs in the packages\n\
+ com.sun.javadoc, com.sun.tools.doclets and their implementations\n\
+ are planned to be removed in a future JDK release. These\n\
+ components have been superseded by the new APIs in jdk.javadoc.doclet.\n\
+ Users are strongly recommended to migrate to the new APIs.\n
+
javadoc.class_not_found=Class {0} not found.
javadoc.error=error
javadoc.warning=warning
-
javadoc.error.msg={0}: error - {1}
javadoc.warning.msg={0}: warning - {1}
javadoc.note.msg = {1}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java Fri May 06 06:23:30 2016 -0700
@@ -35,6 +35,7 @@
class ArgTokenizer {
private final String str;
+ private final String prefix;
private final int length;
private int next = 0;
private char buf[] = new char[20];
@@ -49,7 +50,12 @@
private boolean isQuoted = false;
ArgTokenizer(String arg) {
+ this("", arg);
+ }
+
+ ArgTokenizer(String prefix, String arg) {
this.str = arg;
+ this.prefix = prefix;
this.length = arg.length();
quoteChar('"');
quoteChar('\'');
@@ -88,7 +94,7 @@
}
String whole() {
- return str;
+ return prefix + str;
}
void mark() {
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Fri May 06 06:23:30 2016 -0700
@@ -95,20 +95,20 @@
return mode.getContinuationPrompt(nextId);
}
- public boolean setFeedback(JShellTool tool, ArgTokenizer at) {
- return new Setter(tool, at).setFeedback();
+ public boolean setFeedback(MessageHandler messageHandler, ArgTokenizer at) {
+ return new Setter(messageHandler, at).setFeedback();
}
- public boolean setFormat(JShellTool tool, ArgTokenizer at) {
- return new Setter(tool, at).setFormat();
+ public boolean setFormat(MessageHandler messageHandler, ArgTokenizer at) {
+ return new Setter(messageHandler, at).setFormat();
}
- public boolean setNewMode(JShellTool tool, ArgTokenizer at) {
- return new Setter(tool, at).setNewMode();
+ public boolean setNewMode(MessageHandler messageHandler, ArgTokenizer at) {
+ return new Setter(messageHandler, at).setNewMode();
}
- public boolean setPrompt(JShellTool tool, ArgTokenizer at) {
- return new Setter(tool, at).setPrompt();
+ public boolean setPrompt(MessageHandler messageHandler, ArgTokenizer at) {
+ return new Setter(messageHandler, at).setPrompt();
}
{
@@ -529,26 +529,26 @@
private class Setter {
private final ArgTokenizer at;
- private final JShellTool tool;
+ private final MessageHandler messageHandler;
boolean valid = true;
- Setter(JShellTool tool, ArgTokenizer at) {
- this.tool = tool;
+ Setter(MessageHandler messageHandler, ArgTokenizer at) {
+ this.messageHandler = messageHandler;
this.at = at;
}
void fluff(String format, Object... args) {
- tool.fluff(format, args);
+ messageHandler.fluff(format, args);
}
- void fluffmsg(String format, Object... args) {
- tool.fluffmsg(format, args);
+ void fluffmsg(String messageKey, Object... args) {
+ messageHandler.fluffmsg(messageKey, args);
}
void errorat(String messageKey, Object... args) {
Object[] a2 = Arrays.copyOf(args, args.length + 2);
- a2[args.length] = "/set " + at.whole();
- tool.errormsg(messageKey, a2);
+ a2[args.length] = at.whole();
+ messageHandler.errormsg(messageKey, a2);
}
// For /set prompt <mode> "<prompt>" "<continuation-prompt>"
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Fri May 06 06:23:30 2016 -0700
@@ -108,7 +108,7 @@
* Command line REPL tool for Java using the JShell API.
* @author Robert Field
*/
-public class JShellTool {
+public class JShellTool implements MessageHandler {
private static final String LINE_SEP = System.getProperty("line.separator");
private static final Pattern LINEBREAK = Pattern.compile("\\R");
@@ -166,6 +166,8 @@
private boolean regenerateOnDeath = true;
private boolean live = false;
private boolean feedbackInitialized = false;
+ private String initialMode = null;
+ private List<String> remoteVMOptions = new ArrayList<>();
SourceCodeAnalysis analysis;
JShell state = null;
@@ -256,7 +258,8 @@
* @param format printf format
* @param args printf args
*/
- void fluff(String format, Object... args) {
+ @Override
+ public void fluff(String format, Object... args) {
if (feedback.shouldDisplayCommandFluff() && interactive()) {
hard(format, args);
}
@@ -362,7 +365,8 @@
* @param key the resource key
* @param args
*/
- void errormsg(String key, Object... args) {
+ @Override
+ public void errormsg(String key, Object... args) {
cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre()));
}
@@ -383,7 +387,8 @@
* @param key the resource key
* @param args
*/
- void fluffmsg(String key, Object... args) {
+ @Override
+ public void fluffmsg(String key, Object... args) {
if (feedback.shouldDisplayCommandFluff() && interactive()) {
hardmsg(key, args);
}
@@ -512,6 +517,23 @@
case "-fullversion":
cmdout.printf("jshell %s\n", fullVersion());
return null;
+ case "-feedback":
+ if (ai.hasNext()) {
+ initialMode = ai.next();
+ } else {
+ startmsg("jshell.err.opt.feedback.arg");
+ return null;
+ }
+ break;
+ case "-q":
+ initialMode = "concise";
+ break;
+ case "-qq":
+ initialMode = "silent";
+ break;
+ case "-v":
+ initialMode = "verbose";
+ break;
case "-startup":
if (cmdlineStartup != null) {
startmsg("jshell.err.opt.startup.conflict");
@@ -530,6 +552,10 @@
cmdlineStartup = "";
break;
default:
+ if (arg.startsWith("-R")) {
+ remoteVMOptions.add(arg.substring(2));
+ break;
+ }
startmsg("jshell.err.opt.unknown", arg);
printUsage();
return null;
@@ -567,6 +593,7 @@
.idGenerator((sn, i) -> (currentNameSpace == startNamespace || state.status(sn).isActive)
? currentNameSpace.tid(sn)
: errorNamespace.tid(sn))
+ .remoteVMOptions(remoteVMOptions.toArray(new String[remoteVMOptions.size()]))
.build();
shutdownSubscription = state.onShutdown((JShell deadState) -> {
if (deadState == state) {
@@ -596,6 +623,26 @@
start = cmdlineStartup;
}
startUpRun(start);
+ if (initialMode != null) {
+ MessageHandler mh = new MessageHandler() {
+ @Override
+ public void fluff(String format, Object... args) {
+ }
+
+ @Override
+ public void fluffmsg(String messageKey, Object... args) {
+ }
+
+ @Override
+ public void errormsg(String messageKey, Object... args) {
+ startmsg(messageKey, args);
+ }
+ };
+ if (!feedback.setFeedback(mh, new ArgTokenizer("-feedback ", initialMode))) {
+ regenerateOnDeath = false;
+ }
+ initialMode = null;
+ }
currentNameSpace = mainNamespace;
}
//where
@@ -1050,7 +1097,7 @@
"format", "feedback", "newmode", "prompt", "editor", "start"};
final boolean cmdSet(String arg) {
- ArgTokenizer at = new ArgTokenizer(arg.trim());
+ ArgTokenizer at = new ArgTokenizer("/set ", arg.trim());
String which = setSubCommand(at);
if (which == null) {
return false;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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.internal.jshell.tool;
+
+
+/**
+ * User message reporting support
+ *
+ * @author Robert Field
+ */
+public interface MessageHandler {
+
+ void fluff(String format, Object... args);
+
+ void fluffmsg(String messageKey, Object... args);
+
+ void errormsg(String messageKey, Object... args);
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Fri May 06 06:23:30 2016 -0700
@@ -28,6 +28,7 @@
For an introduction type: /help intro\n
jshell.err.opt.classpath.conflict = Conflicting -classpath option.
jshell.err.opt.classpath.arg = Argument to -classpath missing.
+jshell.err.opt.feedback.arg = Argument to -feedback missing. Mode required.
jshell.err.opt.startup.conflict = Conflicting -startup or -nostartup option.
jshell.err.opt.unknown = Unknown option: {0}
@@ -128,13 +129,23 @@
help.usage = \
Usage: jshell <options> <load files>\n\
-where possible options include:\n\t\
- -classpath <path> Specify where to find user class files\n\t\
- -cp <path> Specify where to find user class files\n\t\
- -startup <file> One run replacement for the start-up definitions\n\t\
- -nostartup Do not run the start-up definitions\n\t\
- -help Print a synopsis of standard options\n\t\
- -version Version information\n
+where possible options include:\n\
+\ -classpath <path> Specify where to find user class files\n\
+\ -cp <path> Specify where to find user class files\n\
+\ -startup <file> One run replacement for the start-up definitions\n\
+\ -nostartup Do not run the start-up definitions\n\
+\ -feedback <mode> Specify the initial feedback mode. The mode may be\n\
+\ predefined (silent, concise, normal, or verbose) or\n\
+\ previously user-defined\n\
+\ -q Quiet feedback. Same as: -feedback concise\n\
+\ -qq Really quiet feedback. Same as: -feedback silent\n\
+\ -v Verbose feedback. Same as: -feedback verbose\n\
+\ -J<flag> Pass <flag> directly to the runtime system.\n\
+\ Use one -J for each runtime flag or flag argument\n\
+\ -R<flag> Pass <flag> to the remote runtime system.\n\
+\ Use one -R for each remote flag or flag argument\n\
+\ -help Print this synopsis of standard options\n\
+\ -version Version information\n
help.list.summary = list the source you have typed
help.list.args = [all|start|<name or id>]
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java Fri May 06 06:23:30 2016 -0700
@@ -36,12 +36,18 @@
// Simplified view on compiler Diagnostic.
/**
+ * In-package creation only.
+ */
+ Diag() {
+ }
+
+ /**
* Used to signal that no position is available.
*/
public final static long NOPOS = Diagnostic.NOPOS;
/**
- * Is this diagnostic and error (as opposed to a warning or note)
+ * Is this diagnostic an error (as opposed to a warning or note)
* @return true if this diagnostic is an error
*/
public abstract boolean isError();
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Fri May 06 06:23:30 2016 -0700
@@ -452,7 +452,7 @@
// If appropriate, execute the snippet
String value = null;
- Exception exception = null;
+ JShellException exception = null;
if (si.status().isDefined) {
if (si.isExecutable()) {
try {
@@ -462,7 +462,8 @@
: "";
} catch (EvalException ex) {
exception = translateExecutionException(ex);
- } catch (UnresolvedReferenceException ex) {
+ } catch (JShellException ex) {
+ // UnresolvedReferenceException
exception = ex;
}
} else if (si.subKind() == SubKind.VAR_DECLARATION_SUBKIND) {
@@ -499,7 +500,7 @@
|| e.exception() != null;
}
- private List<SnippetEvent> events(Unit c, Collection<Unit> outs, String value, Exception exception) {
+ private List<SnippetEvent> events(Unit c, Collection<Unit> outs, String value, JShellException exception) {
List<SnippetEvent> events = new ArrayList<>();
events.add(c.event(value, exception));
events.addAll(outs.stream()
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java Fri May 06 06:23:30 2016 -0700
@@ -40,7 +40,7 @@
* empty string.
*/
@SuppressWarnings("serial") // serialVersionUID intentionally omitted
-public class EvalException extends Exception {
+public class EvalException extends JShellException {
private final String exceptionClass;
EvalException(String message, String exceptionClass, StackTraceElement[] stackElements) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Fri May 06 06:23:30 2016 -0700
@@ -57,11 +57,19 @@
private ObjectInputStream in;
private ObjectOutputStream out;
private final JShell proc;
+ private final String remoteVMOptions;
- ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc) {
+ ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc, List<String> extraRemoteVMOptions) {
this.env = env;
this.maps = maps;
this.proc = proc;
+ StringBuilder sb = new StringBuilder();
+ extraRemoteVMOptions.stream()
+ .forEach(s -> {
+ sb.append(" ");
+ sb.append(s);
+ });
+ this.remoteVMOptions = sb.toString();
}
void launch() throws IOException {
@@ -111,7 +119,7 @@
}
}
- String commandInvoke(String classname) throws EvalException, UnresolvedReferenceException {
+ String commandInvoke(String classname) throws JShellException {
try {
synchronized (STOP_LOCK) {
userCodeRunning = true;
@@ -205,7 +213,7 @@
}
}
- private boolean readAndReportExecutionResult() throws IOException, EvalException, UnresolvedReferenceException {
+ private boolean readAndReportExecutionResult() throws IOException, JShellException {
int ok = in.readInt();
switch (ok) {
case RESULT_SUCCESS:
@@ -257,11 +265,9 @@
// Locale.getDefault());
String connectorName = "com.sun.jdi.CommandLineLaunch";
- String classPath = System.getProperty("java.class.path");
- String javaArgs = "-classpath " + classPath;
Map<String, String> argumentName2Value = new HashMap<>();
argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port);
- argumentName2Value.put("options", javaArgs);
+ argumentName2Value.put("options", remoteVMOptions);
boolean launchImmediately = true;
int traceFlags = 0;// VirtualMachine.TRACE_SENDS | VirtualMachine.TRACE_EVENTS;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Fri May 06 06:23:30 2016 -0700
@@ -26,10 +26,11 @@
package jdk.jshell;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -84,6 +85,7 @@
final PrintStream err;
final Supplier<String> tempVariableNameGenerator;
final BiFunction<Snippet, Integer, String> idGenerator;
+ final List<String> extraRemoteVMOptions;
private int nextKeyIndex = 1;
@@ -105,6 +107,7 @@
this.err = b.err;
this.tempVariableNameGenerator = b.tempVariableNameGenerator;
this.idGenerator = b.idGenerator;
+ this.extraRemoteVMOptions = b.extraRemoteVMOptions;
this.maps = new SnippetMaps(this);
this.keyMap = new KeyMap(this);
@@ -139,6 +142,7 @@
PrintStream err = System.err;
Supplier<String> tempVariableNameGenerator = null;
BiFunction<Snippet, Integer, String> idGenerator = null;
+ List<String> extraRemoteVMOptions = new ArrayList<>();
Builder() { }
@@ -264,6 +268,18 @@
}
/**
+ * Set additional VM options for launching the VM.
+ *
+ * @param options The options for the remote VM.
+ * @return the <code>Builder</code> instance (for use in chained
+ * initialization).
+ */
+ public Builder remoteVMOptions(String... options) {
+ this.extraRemoteVMOptions.addAll(Arrays.asList(options));
+ return this;
+ }
+
+ /**
* Build a JShell state engine. This is the entry-point to all JShell
* functionality. This creates a remote process for execution. It is
* thus important to close the returned instance.
@@ -621,10 +637,10 @@
ExecutionControl executionControl() {
if (executionControl == null) {
- this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this);
+ this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this, extraRemoteVMOptions);
try {
executionControl.launch();
- } catch (IOException ex) {
+ } catch (Throwable ex) {
throw new InternalError("Launching JDI execution engine threw: " + ex.getMessage(), ex);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.jshell;
+
+/**
+ * The superclass of JShell generated exceptions
+ */
+@SuppressWarnings("serial") // serialVersionUID intentionally omitted
+public class JShellException extends Exception {
+
+ JShellException(String message) {
+ super(message);
+ }
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java Fri May 06 06:23:30 2016 -0700
@@ -44,7 +44,7 @@
SnippetEvent(Snippet snippet, Status previousStatus, Status status,
boolean isSignatureChange, Snippet causeSnippet,
- String value, Exception exception) {
+ String value, JShellException exception) {
this.snippet = snippet;
this.previousStatus = previousStatus;
this.status = status;
@@ -60,7 +60,7 @@
private final boolean isSignatureChange;
private final Snippet causeSnippet;
private final String value;
- private final Exception exception;
+ private final JShellException exception;
/**
* The Snippet which has changed
@@ -121,7 +121,7 @@
* during execution, otherwise <code>null</code>.
* @return the exception or <code>null</code>.
*/
- public Exception exception() {
+ public JShellException exception() {
return exception;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Fri May 06 06:23:30 2016 -0700
@@ -440,7 +440,7 @@
: msi.parameterTypes();
}
- SnippetEvent event(String value, Exception exception) {
+ SnippetEvent event(String value, JShellException exception) {
boolean wasSignatureChanged = sigChanged();
state.debug(DBG_EVNT, "Snippet: %s id: %s before: %s status: %s sig: %b cause: %s\n",
si, si.id(), prevStatus, si.status(), wasSignatureChanged, causalSnippet);
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java Fri May 06 06:23:30 2016 -0700
@@ -38,7 +38,7 @@
* empty string.
*/
@SuppressWarnings("serial") // serialVersionUID intentionally omitted
-public class UnresolvedReferenceException extends Exception {
+public class UnresolvedReferenceException extends JShellException {
final DeclarationSnippet snippet;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,145 @@
+/*
+ * 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 8154119
+ * @summary Test modules support in javadoc.
+ * @author bpatel
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester
+ * @run main TestModules
+ */
+
+public class TestModules extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestModules tester = new TestModules();
+ tester.runTests();
+ }
+
+ @Test
+ void test1() {
+ javadoc("-d", "out",
+ "-modulesourcepath", testSrc,
+ "-addmods", "module1,module2",
+ "testpkgmdl1", "testpkgmdl2");
+ checkExit(Exit.OK);
+ testDescription(true);
+ testNoDescription(false);
+ }
+
+ @Test
+ void test2() {
+ javadoc("-d", "out-html5", "-html5",
+ "-modulesourcepath", testSrc,
+ "-addmods", "module1,module2",
+ "testpkgmdl1", "testpkgmdl2");
+ checkExit(Exit.OK);
+ testHtml5Description(true);
+ testHtml5NoDescription(false);
+ }
+
+ @Test
+ void test3() {
+ javadoc("-d", "out-nocomment", "-nocomment",
+ "-modulesourcepath", testSrc,
+ "-addmods", "module1,module2",
+ "testpkgmdl1", "testpkgmdl2");
+ checkExit(Exit.OK);
+ testDescription(false);
+ testNoDescription(true);
+ }
+
+ @Test
+ void test4() {
+ javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5",
+ "-modulesourcepath", testSrc,
+ "-addmods", "module1,module2",
+ "testpkgmdl1", "testpkgmdl2");
+ checkExit(Exit.OK);
+ testHtml5Description(false);
+ testHtml5NoDescription(true);
+ }
+
+ void testDescription(boolean found) {
+ checkOutput("module1-summary.html", found,
+ "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+ + "<a name=\"module.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ + "<div class=\"block\">This is a test description for the module1 module.</div>");
+ checkOutput("module2-summary.html", found,
+ "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+ + "<a name=\"module.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ + "<div class=\"block\">This is a test description for the module2 module.</div>");
+ }
+
+ void testNoDescription(boolean found) {
+ checkOutput("module1-summary.html", found,
+ "<div class=\"contentContainer\">\n"
+ + "<ul class=\"blockList\">\n"
+ + "<li class=\"blockList\">\n"
+ + "<table class=\"overviewSummary\" summary=\"Package Summary table, listing packages, and an explanation\">");
+ checkOutput("module2-summary.html", found,
+ "<div class=\"contentContainer\">\n"
+ + "<ul class=\"blockList\">\n"
+ + "<li class=\"blockList\">\n"
+ + "<table class=\"overviewSummary\" summary=\"Package Summary table, listing packages, and an explanation\">");
+ }
+
+ void testHtml5Description(boolean found) {
+ checkOutput("module1-summary.html", found,
+ "<section role=\"region\">\n"
+ + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+ + "<a id=\"module.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ + "<div class=\"block\">This is a test description for the module1 module.</div>\n"
+ + "</section>");
+ checkOutput("module2-summary.html", found,
+ "<section role=\"region\">\n"
+ + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+ + "<a id=\"module.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ + "<div class=\"block\">This is a test description for the module2 module.</div>\n"
+ + "</section>");
+ }
+
+ void testHtml5NoDescription(boolean found) {
+ checkOutput("module1-summary.html", found,
+ "<div class=\"contentContainer\">\n"
+ + "<ul class=\"blockList\">\n"
+ + "<li class=\"blockList\">\n"
+ + "<table class=\"overviewSummary\">");
+ checkOutput("module2-summary.html", found,
+ "<div class=\"contentContainer\">\n"
+ + "<ul class=\"blockList\">\n"
+ + "<li class=\"blockList\">\n"
+ + "<table class=\"overviewSummary\">");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is a test description for the module1 module.
+ */
+module module1 {
+ requires module2;
+
+ exports testpkgmdl1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/testpkgmdl1/TestClassInModule1.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,28 @@
+/*
+ * 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 testpkgmdl1;
+
+public class TestClassInModule1 {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is a test description for the module2 module.
+ */
+module module2 {
+ exports testpkgmdl2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,28 @@
+/*
+ * 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 testpkgmdl2;
+
+public class TestClassInModule2 {
+}
--- a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java Fri May 06 06:23:30 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8039410 8042601 8042829 8049393 8050031
+ * @bug 8039410 8042601 8042829 8049393 8050031 8155061
* @summary test to determine if members are ordered correctly
* @author ksrini
* @library ../lib/
@@ -72,6 +72,8 @@
checkOrder("pkg1/class-use/UsedClass.html", expectedInnerClassContructors);
checkOrder("pkg1/ImplementsOrdering.html", expectedImplementsOrdering);
checkOrder("pkg1/OverrideOrdering.html", expectedOverrideOrdering);
+ checkOrder("allclasses-noframe.html", expectedAllClasses);
+ checkOrder("allclasses-frame.html", expectedAllClasses);
}
enum ListOrder { NONE, REVERSE, SHUFFLE };
@@ -179,6 +181,22 @@
};
String[] composeTestVectors() {
List<String> testList = new ArrayList<>();
+
+ testList.addAll(Arrays.asList(expectedPackageOrdering));
+
+ for (String x : expectedMethodOrdering) {
+ testList.add(x);
+ for (int i = 0; i < MAX_PACKAGES; i++) {
+ String wpkg = "add" + i;
+ testList.add(wpkg + "/" + x);
+ String dpkg = wpkg;
+ for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) {
+ dpkg = dpkg + "/" + "add";
+ testList.add(dpkg + "/" + x);
+ }
+ }
+ }
+
for (String x : expectedEnumOrdering) {
testList.add(x.replace("REPLACE_ME", "<Unnamed>"));
for (int i = 0; i < MAX_PACKAGES; i++) {
@@ -194,20 +212,9 @@
testList.addAll(Arrays.asList(expectedFieldOrdering));
- for (String x : expectedMethodOrdering) {
- testList.add(x);
- for (int i = 0; i < MAX_PACKAGES; i++) {
- String wpkg = "add" + i;
- testList.add(wpkg + "/" + x);
- String dpkg = wpkg;
- for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) {
- dpkg = dpkg + "/" + "add";
- testList.add(dpkg + "/" + x);
- }
- }
- }
return testList.toArray(new String[testList.size()]);
}
+
void checkExecutableMemberOrdering(String usePage) {
String contents = readFile(usePage);
// check constructors
@@ -309,6 +316,22 @@
return in.replace("/", ".");
}
+ final String expectedAllClasses[] = {
+ "pkg1/A.html\" title=\"class in pkg1",
+ "pkg1/A.C.html\" title=\"class in pkg1",
+ "pkg1/B.html\" title=\"class in pkg1",
+ "pkg1/B.A.html\" title=\"class in pkg1",
+ "pkg1/C1.html\" title=\"class in pkg1",
+ "pkg1/C2.html\" title=\"class in pkg1",
+ "pkg1/C3.html\" title=\"class in pkg1",
+ "pkg1/C4.html\" title=\"class in pkg1",
+ "pkg1/ImplementsOrdering.html\" title=\"interface in pkg1",
+ "pkg1/MethodOrder.html\" title=\"class in pkg1",
+ "pkg1/OverrideOrdering.html\" title=\"class in pkg1",
+ "pkg1/UsedClass.html\" title=\"class in pkg1"
+
+ };
+
final String expectedInnerClassContructors[] = {
"../../pkg1/A.html#A-pkg1.UsedClass-",
"../../pkg1/B.A.html#A-pkg1.UsedClass-",
@@ -342,12 +365,33 @@
"../../pkg1/MethodOrder.html#m-java.util.Collection-",
"../../pkg1/MethodOrder.html#m-java.util.List-"
};
+
final String expectedClassUseWithTypeParams[] = {
"../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-",
"../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass-",
"../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass:A-",
"../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-java.lang.String-"
};
+
+ final String expectedPackageOrdering[] = {
+ "\"add0/package-summary.html\">add0</a> - package add0",
+ "\"add0/add/package-summary.html\">add0.add</a> - package add0.add",
+ "\"add0/add/add/package-summary.html\">add0.add.add</a> - package add0.add.add",
+ "\"add0/add/add/add/package-summary.html\">add0.add.add.add</a> - package add0.add.add.add",
+ "\"add1/package-summary.html\">add1</a> - package add1",
+ "\"add1/add/package-summary.html\">add1.add</a> - package add1.add",
+ "\"add1/add/add/package-summary.html\">add1.add.add</a> - package add1.add.add",
+ "\"add1/add/add/add/package-summary.html\">add1.add.add.add</a> - package add1.add.add.add",
+ "\"add2/package-summary.html\">add2</a> - package add2",
+ "\"add2/add/package-summary.html\">add2.add</a> - package add2.add",
+ "\"add2/add/add/package-summary.html\">add2.add.add</a> - package add2.add.add",
+ "\"add2/add/add/add/package-summary.html\">add2.add.add.add</a> - package add2.add.add.add",
+ "\"add3/package-summary.html\">add3</a> - package add3",
+ "\"add3/add/package-summary.html\">add3.add</a> - package add3.add",
+ "\"add3/add/add/package-summary.html\">add3.add.add</a> - package add3.add.add",
+ "\"add3/add/add/add/package-summary.html\">add3.add.add.add</a> - package add3.add.add.add"
+ };
+
final String expectedMethodOrdering[] = {
"Add.html#add--",
"Add.html#add-double-",
@@ -361,10 +405,12 @@
"Add.html#add-java.lang.Double-",
"Add.html#add-java.lang.Integer-"
};
+
final String expectedEnumOrdering[] = {
"Add.add.html\" title=\"enum in REPLACE_ME\"",
"Add.ADD.html\" title=\"enum in REPLACE_ME\""
};
+
final String expectedFieldOrdering[] = {
"Add.html#addadd\"",
"add0/add/add/add/Add.html#addadd\"",
@@ -418,10 +464,12 @@
"add3/add/Add.html#ADDADD\"",
"add3/Add.html#ADDADD\""
};
+
final String expectedPackageTreeOrdering[] = {
"<a href=\"../../add0/add/Add.add.html\" title=\"enum in add0.add\">",
"<a href=\"../../add0/add/Add.ADD.html\" title=\"enum in add0.add\">"
};
+
final String expectedOverviewOrdering[] = {
"<a href=\"Add.add.html\" title=\"enum in <Unnamed>\">",
"<a href=\"add0/Add.add.html\" title=\"enum in add0\">",
@@ -458,6 +506,7 @@
"<a href=\"add3/add/add/Add.ADD.html\" title=\"enum in add3.add.add\">",
"<a href=\"add3/add/add/add/Add.ADD.html\" title=\"enum in add3.add.add.add\">",
};
+
final static String expectedOverviewFrameOrdering[] = {
"<a href=\"package-frame.html\" target=\"packageFrame\"><unnamed package></a>",
"<a href=\"add0/package-frame.html\" target=\"packageFrame\">add0</a>",
@@ -477,11 +526,13 @@
"<a href=\"add3/add/add/package-frame.html\" target=\"packageFrame\">add3.add.add</a>",
"<a href=\"add3/add/add/add/package-frame.html\" target=\"packageFrame\">add3.add.add.add</a></li>"
};
+
final static String expectedImplementsOrdering[] = {
"<dd><code>close</code> in interface <code>java.lang.AutoCloseable</code></dd>",
"<dd><code>close</code> in interface <code>java.nio.channels.Channel</code></dd>",
"<dd><code>close</code> in interface <code>java.io.Closeable</code></dd>"
};
+
final static String expectedOverrideOrdering[] = {
"<dd><code>iterator</code> in interface <code>java.util.Collection<",
"<dd><code>iterator</code> in interface <code>java.lang.Iterable<"
--- a/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java Fri May 06 06:23:30 2016 -0700
@@ -23,96 +23,349 @@
/*
* @test
- * @bug 8035473
- * @summary make sure the new doclet is invoked by default, and -Xold
+ * @bug 8035473 8154482
+ * @summary make sure the javadoc tool responds correctly to Xold,
+ * old doclets and taglets.
+ * @library /tools/lib
+ * @build toolbox.ToolBox toolbox.TestRunner
+ * @run main EnsureNewOldDoclet
*/
import java.io.*;
-import java.util.ArrayList;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import com.sun.javadoc.Tag;
+import com.sun.source.doctree.DocTree;
+
+import toolbox.*;
+
/**
- * Dummy javadoc comment.
+ * This test ensures the doclet responds correctly when given
+ * various conditions that force a fall back to the old javadoc
+ * tool. The following condition in the order described will
+ * force a dispatch to the old tool, -Xold, old doclet and old taglet.
+ *
*/
-public class EnsureNewOldDoclet {
+public class EnsureNewOldDoclet extends TestRunner {
+
+ final ToolBox tb;
+ final File testSrc;
+ final Path javadocPath;
+ final ExecTask task;
+ final String testClasses;
+ final PrintStream ostream;
- final File javadoc;
- final File testSrc;
- final String thisClassName;
+ final static String CLASS_NAME = "EnsureNewOldDoclet";
+ final static String OLD_DOCLET_CLASS_NAME = CLASS_NAME + "$OldDoclet";
+ final static String NEW_DOCLET_CLASS_NAME = CLASS_NAME + "$NewDoclet"; //unused
+ final static String OLD_TAGLET_CLASS_NAME = CLASS_NAME + "$OldTaglet";
+ final static String NEW_TAGLET_CLASS_NAME = CLASS_NAME + "$NewTaglet";
+
+ final static Pattern OLD_HEADER = Pattern.compile("^Standard Doclet \\(Old\\) version.*");
+ final static Pattern NEW_HEADER = Pattern.compile("^Standard Doclet version.*");
+
+
+ final static String OLD_DOCLET_MARKER = "OLD_DOCLET_MARKER";
+ final static String OLD_TAGLET_MARKER = "Registered: OldTaglet";
+
+ final static String NEW_DOCLET_MARKER = "NEW_DOCLET_MARKER";
+ final static String NEW_TAGLET_MARKER = "Registered Taglet " + CLASS_NAME + "\\$NewTaglet";
- final static Pattern Expected1 = Pattern.compile("^Standard Doclet \\(Next\\) version.*");
- final static Pattern Expected2 = Pattern.compile("^Standard Doclet version.*");
+ final static Pattern WARN_TEXT = Pattern.compile("Users are strongly recommended to migrate" +
+ " to the new APIs.");
+ final static String OLD_DOCLET_ERROR = "java.lang.NoSuchMethodException: " +
+ CLASS_NAME +"\\$NewTaglet";
+ final static Pattern NEW_DOCLET_ERROR = Pattern.compile(".*java.lang.ClassCastException.*Taglet " +
+ CLASS_NAME + "\\$OldTaglet.*");
+
+ final static String OLD_STDDOCLET = "com.sun.tools.doclets.standard.Standard";
+ final static String NEW_STDDOCLET = "jdk.javadoc.internal.doclets.standard.Standard";
+
- public EnsureNewOldDoclet() {
- File javaHome = new File(System.getProperty("java.home"));
- if (javaHome.getName().endsWith("jre"))
- javaHome = javaHome.getParentFile();
- javadoc = new File(new File(javaHome, "bin"), "javadoc");
- testSrc = new File(System.getProperty("test.src"));
- thisClassName = EnsureNewOldDoclet.class.getName();
+ public EnsureNewOldDoclet() throws Exception {
+ super(System.err);
+ ostream = System.err;
+ testClasses = System.getProperty("test.classes");
+ tb = new ToolBox();
+ javadocPath = tb.getJDKTool("javadoc");
+ task = new ExecTask(tb, javadocPath);
+ testSrc = new File("Foo.java");
+ generateSample(testSrc);
+ }
+
+ void generateSample(File testSrc) throws Exception {
+ String nl = System.getProperty("line.separator");
+ String src = Arrays.asList(
+ "/**",
+ " * A test class to test javadoc. Nothing more nothing less.",
+ " */",
+ " public class Foo{}").stream().collect(Collectors.joining(nl));
+ tb.writeFile(testSrc.getPath(), src);
}
public static void main(String... args) throws Exception {
- EnsureNewOldDoclet test = new EnsureNewOldDoclet();
- test.run1();
- test.run2();
+ new EnsureNewOldDoclet().runTests();
+ }
+
+ // input: nothing, default mode
+ // outcome: new tool and new doclet
+ @Test
+ public void testDefault() throws Exception {
+ setArgs("-classpath", ".", // insulates us from ambient classpath
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.SUCCESS);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ checkOutput(testName, out, NEW_HEADER);
+ }
+
+ // input: -Xold
+ // outcome: old tool
+ @Test
+ public void testXold() throws Exception {
+ setArgs("-Xold",
+ "-classpath", ".", // ambient classpath insulation
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.SUCCESS);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, OLD_HEADER);
+ checkOutput(testName, err, WARN_TEXT);
+ }
+
+ // input: old doclet
+ // outcome: old tool
+ @Test
+ public void testOldDoclet() throws Exception {
+ setArgs("-classpath", ".", // ambient classpath insulation
+ "-doclet",
+ OLD_DOCLET_CLASS_NAME,
+ "-docletpath",
+ testClasses,
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.SUCCESS);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, OLD_DOCLET_MARKER);
+ checkOutput(testName, err, WARN_TEXT);
+ }
+
+ // input: old taglet
+ // outcome: old tool
+ @Test
+ public void testOldTaglet() throws Exception {
+ setArgs("-classpath", ".", // ambient classpath insulation
+ "-taglet",
+ OLD_TAGLET_CLASS_NAME,
+ "-tagletpath",
+ testClasses,
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.SUCCESS);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, OLD_TAGLET_MARKER);
+ checkOutput(testName, err, WARN_TEXT);
}
- // make sure new doclet is invoked by default
- void run1() throws Exception {
- List<String> output = doTest(javadoc.getPath(),
- "-classpath", ".", // insulates us from ambient classpath
- "-Xdoclint:none",
- "-package",
- new File(testSrc, thisClassName + ".java").getPath());
- System.out.println(output);
- for (String x : output) {
- if (Expected1.matcher(x).matches()) {
+ // input: new doclet and old taglet
+ // outcome: new doclet with failure
+ @Test
+ public void testNewDocletOldTaglet() throws Exception {
+ setArgs("-classpath", ".", // ambient classpath insulation
+ "-doclet",
+ NEW_STDDOCLET,
+ "-taglet",
+ OLD_TAGLET_CLASS_NAME,
+ "-tagletpath",
+ testClasses,
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.FAIL, 1);
+ //Task.Result tr = task.run();
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, NEW_HEADER);
+ checkOutput(testName, err, NEW_DOCLET_ERROR);
+ }
+
+ // input: old doclet and old taglet
+ // outcome: old doclet and old taglet should register
+ @Test
+ public void testOldDocletOldTaglet() throws Exception {
+ setArgs("-classpath", ".", // ambient classpath insulation
+ "-doclet",
+ OLD_STDDOCLET,
+ "-taglet",
+ OLD_TAGLET_CLASS_NAME,
+ "-tagletpath",
+ testClasses,
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.SUCCESS);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, OLD_HEADER);
+ checkOutput(testName, out, OLD_TAGLET_MARKER);
+ checkOutput(testName, err, WARN_TEXT);
+ }
+
+ // input: new doclet and new taglet
+ // outcome: new doclet and new taglet should register
+ @Test
+ public void testNewDocletNewTaglet() throws Exception {
+ setArgs("-classpath", ".", // ambient classpath insulation
+ "-doclet",
+ NEW_STDDOCLET,
+ "-taglet",
+ NEW_TAGLET_CLASS_NAME,
+ "-tagletpath",
+ testClasses,
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.SUCCESS);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, NEW_HEADER);
+ checkOutput(testName, out, NEW_TAGLET_MARKER);
+ }
+
+ // input: old doclet and new taglet
+ // outcome: old doclet and error
+ @Test
+ public void testOldDocletNewTaglet() throws Exception {
+ setArgs("-classpath", ".", // ambient classpath insulation
+ "-doclet",
+ OLD_STDDOCLET,
+ "-taglet",
+ NEW_TAGLET_CLASS_NAME,
+ "-tagletpath",
+ testClasses,
+ testSrc.toString());
+ Task.Result tr = task.run(Task.Expect.FAIL, 1);
+ List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+ List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+ checkOutput(testName, out, OLD_HEADER);
+ checkOutput(testName, err, WARN_TEXT);
+ checkOutput(testName, err, OLD_DOCLET_ERROR);
+ }
+
+ void setArgs(String... args) {
+ ostream.println("cmds: " + Arrays.asList(args));
+ task.args(args);
+ }
+
+ void checkOutput(String testCase, List<String> content, String toFind) throws Exception {
+ checkOutput(testCase, content, Pattern.compile(".*" + toFind + ".*"));
+ }
+
+ void checkOutput(String testCase, List<String> content, Pattern toFind) throws Exception {
+ ostream.println("---" + testCase + "---");
+ content.stream().forEach(x -> System.out.println(x));
+ for (String x : content) {
+ ostream.println(x);
+ if (toFind.matcher(x).matches()) {
return;
}
}
- throw new Exception("run1: Expected string not found:");
+ throw new Exception(testCase + ": Expected string not found: " + toFind);
}
- // make sure the old doclet is invoked with -Xold
- void run2() throws Exception {
- List<String> output = doTest(javadoc.getPath(),
- "-Xold",
- "-classpath", ".", // insulates us from ambient classpath
- "-Xdoclint:none",
- "-package",
- new File(testSrc, thisClassName + ".java").getPath());
-
- for (String x : output) {
- if (Expected2.matcher(x).matches()) {
- throw new Exception("run2: Expected string not found");
- }
- return;
+ public static class OldDoclet extends com.sun.javadoc.Doclet {
+ public static boolean start(com.sun.javadoc.RootDoc root) {
+ System.out.println(OLD_DOCLET_MARKER);
+ return true;
}
}
- /**
- * More dummy comments.
- */
- List<String> doTest(String... args) throws Exception {
- List<String> output = new ArrayList<>();
- // run javadoc in separate process to ensure doclet executed under
- // normal user conditions w.r.t. classloader
- Process p = new ProcessBuilder()
- .command(args)
- .redirectErrorStream(true)
- .start();
- try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
- String line = in.readLine();
- while (line != null) {
- output.add(line.trim());
- line = in.readLine();
- }
+ public static class OldTaglet implements com.sun.tools.doclets.Taglet {
+
+ public static void register(Map map) {
+ EnsureNewOldDoclet.OldTaglet tag = new OldTaglet();
+ com.sun.tools.doclets.Taglet t = (com.sun.tools.doclets.Taglet) map.get(tag.getName());
+ System.out.println(OLD_TAGLET_MARKER);
+ }
+
+ @Override
+ public boolean inField() {
+ return true;
+ }
+
+ @Override
+ public boolean inConstructor() {
+ return true;
+ }
+
+ @Override
+ public boolean inMethod() {
+ return true;
+ }
+
+ @Override
+ public boolean inOverview() {
+ return true;
+ }
+
+ @Override
+ public boolean inPackage() {
+ return true;
+ }
+
+ @Override
+ public boolean inType() {
+ return true;
+ }
+
+ @Override
+ public boolean isInlineTag() {
+ return true;
}
- int rc = p.waitFor();
- if (rc != 0)
- throw new Exception("javadoc failed, rc:" + rc);
- return output;
+
+ @Override
+ public String getName() {
+ return "OldTaglet";
+ }
+
+ @Override
+ public String toString(Tag tag) {
+ return getName();
+ }
+
+ @Override
+ public String toString(Tag[] tags) {
+ return getName();
+ }
+ }
+
+ public static class NewTaglet implements jdk.javadoc.doclet.taglet.Taglet {
+
+ @Override
+ public Set<Location> getAllowedLocations() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isInlineTag() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return "NewTaglet";
+ }
+
+ @Override
+ public String toString(DocTree tag) {
+ return tag.toString();
+ }
+
+ @Override
+ public String toString(List<? extends DocTree> tags) {
+ return tags.toString();
+ }
+
}
}
--- a/langtools/test/jdk/jshell/StartOptionTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/jdk/jshell/StartOptionTest.java Fri May 06 06:23:30 2016 -0700
@@ -22,7 +22,7 @@
*/
/*
- * @test
+ * @test 8151754
* @summary Testing start-up options.
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -34,6 +34,7 @@
*/
import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
@@ -47,6 +48,7 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
@Test
public class StartOptionTest {
@@ -55,9 +57,24 @@
private ByteArrayOutputStream err;
private JShellTool getShellTool() {
- return new JShellTool(null, new PrintStream(out), new PrintStream(err), null, null, null,
- null, new ReplToolTesting.MemoryPreferences(),
- Locale.ROOT);
+ class NoOutputAllowedStream extends OutputStream {
+ private final String label;
+ NoOutputAllowedStream(String label) {
+ this.label = label;
+ }
+ @Override
+ public void write(int b) { fail("Unexpected output to: " + label); }
+ }
+ return new JShellTool(
+ new TestingInputStream(),
+ new PrintStream(out),
+ new PrintStream(err),
+ new PrintStream(new NoOutputAllowedStream("console")),
+ new TestingInputStream(),
+ new PrintStream(new NoOutputAllowedStream("userout")),
+ new PrintStream(new NoOutputAllowedStream("usererr")),
+ new ReplToolTesting.MemoryPreferences(),
+ Locale.ROOT);
}
private String getOutput() {
@@ -133,6 +150,12 @@
}
@Test
+ public void testNegFeedbackOption() throws Exception {
+ start("", "Argument to -feedback missing. Mode required.", "-feedback");
+ start("", "Does not match any current feedback mode: blorp -- -feedback blorp", "-feedback", "blorp");
+ }
+
+ @Test
public void testVersion() throws Exception {
start(s -> assertTrue(s.startsWith("jshell")), null, "-version");
}
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Fri May 06 06:23:30 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8153716 8143955
+ * @bug 8153716 8143955 8151754 8150382
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -349,4 +349,39 @@
System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless);
}
}
+
+ public void testOptionQ() {
+ test(new String[]{"-q", "-nostartup"},
+ (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
+ (a) -> assertCommand(a, "int x = 5", "")
+ );
+ }
+
+ public void testOptionQq() {
+ test(new String[]{"-qq", "-nostartup"},
+ (a) -> assertCommand(a, "1+1", "")
+ );
+ }
+
+ public void testOptionV() {
+ test(new String[]{"-v", "-nostartup"},
+ (a) -> assertCommand(a, "1+1",
+ "$1 ==> 2\n" +
+ "| created scratch variable $1 : int")
+ );
+ }
+
+ public void testOptionFeedback() {
+ test(new String[]{"-feedback", "concise", "-nostartup"},
+ (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
+ (a) -> assertCommand(a, "int x = 5", "")
+ );
+ }
+
+ public void testOptionR() {
+ test(new String[]{"-R-Dthe.sound=blorp", "-nostartup"},
+ (a) -> assertCommand(a, "System.getProperty(\"the.sound\")",
+ "$1 ==> \"blorp\"")
+ );
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/UnreachableLoopCond.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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 8155028
+ * @summary javac crashes in silly do-while loop
+ * @compile UnreachableLoopCond.java
+ */
+
+class UnreachableLoopCond {
+
+ public void foo() {
+ Integer i = 100;
+ do {
+ return;
+ } while (i++ < 10);
+ }
+
+ public void goo() {
+ Integer i = 100;
+ do {
+ break;
+ } while (i++ < 10);
+ }
+
+ public void zoo() {
+ Integer i = 100;
+ do {
+ throw new RuntimeException();
+ } while (i++ < 10);
+ }
+
+ public void loo() {
+ Integer i = 100;
+ Integer j = 100;
+ do {
+ do {
+ return;
+ } while (i++ < 10);
+ } while (j++ < 10);
+ }
+
+ public void moo() {
+ Integer i = 100;
+ do {
+ if (true) {
+ return;
+ } else {
+ return;
+ }
+ } while (i++ < 10);
+ }
+
+ public void moo(boolean cond) {
+ Integer i = 100;
+ do {
+ if (cond) {
+ return;
+ } else {
+ return;
+ }
+ } while (i++ < 10);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/T8154270/EraseClassInfoAnnotationValueTest.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Google Inc. 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.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8154270
+ * @summary javac wrongly rejects some class literals as annotation element values
+ * @compile EraseClassInfoAnnotationValueTest.java
+ * @compile -implicit:none Other.java
+ * @run main EraseClassInfoAnnotationValueTest
+ */
+public class EraseClassInfoAnnotationValueTest {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface A {
+ Class<?> value();
+ }
+
+ static class ParametricType<T> {
+
+ @A(Inner.class)
+ public static class Nested {}
+
+ public class Inner {}
+ }
+
+ public static void main(String[] args) {
+ Class<?> clazz = ParametricType.Nested.class.getAnnotation(A.class).value();
+ if (!clazz.equals(ParametricType.Inner.class)) {
+ throw new AssertionError(clazz);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/T8154270/Other.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Google Inc. 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.
+ */
+
+/**
+ * Tests separate compilation.
+ */
+public class Other {
+ Class<?> clazz = EraseClassInfoAnnotationValueTest.ParametricType.Nested.class;
+}
--- a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java Fri May 06 06:23:30 2016 -0700
@@ -191,7 +191,7 @@
CONDITION("int res = \n" +
"testField == 2 ?\n" +
"10\n" +
- ":9;", 1, 3, 4), // see issue https://bugs.openjdk.java.net/browse/JDK-8050993
+ ":9;", 2, 3, 4),
TRY("try{\n" +
" --testField;\n" +
"}\n" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8050993
+ * @summary Verify that the condition in the conditional lexpression gets a LineNumberTable entry
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * @compile -g T8050993.java
+ * @run main T8050993
+ */
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.sun.tools.classfile.*;
+
+public class T8050993 {
+ public static void main(String[] args) throws IOException, ConstantPoolException {
+ ClassFile someTestIn = ClassFile.read(T8050993.class.getResourceAsStream("T8050993.class"));
+ Set<Integer> expectedLineNumbers = new HashSet<>(Arrays.asList(49, 50, 47, 48));
+ for (Method m : someTestIn.methods) {
+ if ("method".equals(m.getName(someTestIn.constant_pool))) {
+ Code_attribute code_attribute = (Code_attribute) m.attributes.get(Attribute.Code);
+ for (Attribute at : code_attribute.attributes) {
+ if (Attribute.LineNumberTable.equals(at.getName(someTestIn.constant_pool))) {
+ LineNumberTable_attribute att = (LineNumberTable_attribute) at;
+ Set<Integer> actualLinesNumbers = Arrays.stream(att.line_number_table)
+ .map(e -> e.line_number)
+ .collect(Collectors.toSet());
+ if (!Objects.equals(expectedLineNumbers, actualLinesNumbers)) {
+ throw new AssertionError("Expected LineNumber entries not found;" +
+ "actual=" + actualLinesNumbers + ";" +
+ "expected=" + expectedLineNumbers);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static int field;
+
+ public static String method() {
+ String s =
+ field % 2 == 0 ?
+ "true" + field :
+ "false" + field;
+ return s;
+ }
+
+}
--- a/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java Fri May 06 06:23:30 2016 -0700
@@ -47,7 +47,7 @@
}
@Test
- void testAbstractServiceImpl(Path base) throws Exception {
+ public void testAbstractServiceImpl(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.Service with p2.Impl; }",
@@ -68,7 +68,7 @@
}
@Test
- void testInnerClassServiceImpl(Path base) throws Exception {
+ public void testInnerClassServiceImpl(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.Service with p2.Outer.Inner; }",
@@ -89,7 +89,7 @@
}
@Test
- void testInnerInterfaceServiceImpl(Path base) throws Exception {
+ public void testInnerInterfaceServiceImpl(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.Service with p2.Outer.Inner; }",
--- a/langtools/test/tools/javac/modules/AddLimitMods.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/AddLimitMods.java Fri May 06 06:23:30 2016 -0700
@@ -79,7 +79,7 @@
}
@Test
- void testManual(Path base) throws Exception {
+ public void testManual(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
@@ -176,7 +176,7 @@
}
@Test
- void testAllModulePath(Path base) throws Exception {
+ public void testAllModulePath(Path base) throws Exception {
if (Files.isDirectory(base))
tb.cleanDirectory(base);
@@ -284,7 +284,7 @@
}
@Test
- void testRuntime2Compile(Path base) throws Exception {
+ public void testRuntime2Compile(Path base) throws Exception {
Path classpathSrc = base.resolve("classpath-src");
Path classpathOut = base.resolve("classpath-out");
--- a/langtools/test/tools/javac/modules/AddReadsTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/AddReadsTest.java Fri May 06 06:23:30 2016 -0700
@@ -58,7 +58,7 @@
}
@Test
- void testAddReads(Path base) throws Exception {
+ public void testAddReads(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1,
@@ -150,7 +150,7 @@
}
@Test
- void testAddReadsUnnamedModule(Path base) throws Exception {
+ public void testAddReadsUnnamedModule(Path base) throws Exception {
Path jar = prepareTestJar(base);
Path moduleSrc = base.resolve("module-src");
@@ -175,7 +175,7 @@
}
@Test
- void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
+ public void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
Path jar = prepareTestJar(base);
Path moduleSrc = base.resolve("module-src");
@@ -202,7 +202,7 @@
}
@Test
- void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
+ public void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
Path jar = prepareTestJar(base);
Path src = base.resolve("src");
Path classes = base.resolve("classes");
@@ -223,7 +223,7 @@
}
@Test
- void testAddReadsToJavaBase(Path base) throws Exception {
+ public void testAddReadsToJavaBase(Path base) throws Exception {
Path src = base.resolve("src");
Path classes = base.resolve("classes");
@@ -275,7 +275,7 @@
}
@Test
- void testX(Path base) throws Exception {
+ public void testX(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1,
--- a/langtools/test/tools/javac/modules/AnnotationProcessing.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java Fri May 06 06:23:30 2016 -0700
@@ -68,7 +68,7 @@
}
@Test
- void testAPSingleModule(Path base) throws Exception {
+ public void testAPSingleModule(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
@@ -95,7 +95,7 @@
}
@Test
- void testAPMultiModule(Path base) throws Exception {
+ public void testAPMultiModule(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
Path m2 = moduleSrc.resolve("m2");
@@ -196,7 +196,7 @@
}
@Test
- void testVerifyUsesProvides(Path base) throws Exception {
+ public void testVerifyUsesProvides(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
@@ -254,7 +254,7 @@
}
@Test
- void testPackageNoModule(Path base) throws Exception {
+ public void testPackageNoModule(Path base) throws Exception {
Path src = base.resolve("src");
Path classes = base.resolve("classes");
--- a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java Fri May 06 06:23:30 2016 -0700
@@ -156,7 +156,7 @@
Path classes;
@Test
- void testUseOnlyOneProcessor(Path base) throws Exception {
+ public void testUseOnlyOneProcessor(Path base) throws Exception {
initialization(base);
String log = new JavacTask(tb)
.options("-processormodulepath", processorCompiledModules.toString(),
@@ -172,7 +172,7 @@
}
@Test
- void testAnnotationProcessorExecutionOrder(Path base) throws Exception {
+ public void testAnnotationProcessorExecutionOrder(Path base) throws Exception {
initialization(base);
List<String> log = new JavacTask(tb)
.options("-processormodulepath", processorCompiledModules.toString(),
@@ -202,7 +202,7 @@
}
@Test
- void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception {
+ public void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception {
initialization(base);
String log = new JavacTask(tb)
.options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(),
@@ -218,7 +218,7 @@
}
@Test
- void testOptionsExclusion(Path base) throws Exception {
+ public void testOptionsExclusion(Path base) throws Exception {
initialization(base);
List<String> log = new JavacTask(tb)
.options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(),
--- a/langtools/test/tools/javac/modules/AutomaticModules.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/AutomaticModules.java Fri May 06 06:23:30 2016 -0700
@@ -48,7 +48,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path legacySrc = base.resolve("legacy-src");
tb.writeJavaFiles(legacySrc,
"package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}");
@@ -98,7 +98,7 @@
}
@Test
- void testUnnamedModule(Path base) throws Exception {
+ public void testUnnamedModule(Path base) throws Exception {
Path legacySrc = base.resolve("legacy-src");
tb.writeJavaFiles(legacySrc,
"package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }",
@@ -156,7 +156,7 @@
}
@Test
- void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
+ public void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
Path automaticSrc = base.resolve("automaticSrc");
tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
Path automaticClasses = base.resolve("automaticClasses");
--- a/langtools/test/tools/javac/modules/DoclintOtherModules.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/DoclintOtherModules.java Fri May 06 06:23:30 2016 -0700
@@ -47,7 +47,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path src = base.resolve("src");
Path m1 = src.resolve("m1");
Path m2 = src.resolve("m2");
--- a/langtools/test/tools/javac/modules/DuplicateClassTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/DuplicateClassTest.java Fri May 06 06:23:30 2016 -0700
@@ -47,7 +47,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path m1 = base.resolve("m1");
Path m2 = base.resolve("m2");
tb.writeJavaFiles(m1,
--- a/langtools/test/tools/javac/modules/EdgeCases.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/EdgeCases.java Fri May 06 06:23:30 2016 -0700
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8154283
* @summary tests for multi-module mode compilation
* @library /tools/lib
* @modules
@@ -57,7 +58,6 @@
import toolbox.JarTask;
import toolbox.JavacTask;
import toolbox.Task;
-import toolbox.ToolBox;
public class EdgeCases extends ModuleTestBase {
@@ -66,7 +66,7 @@
}
@Test
- void testAddExportUndefinedModule(Path base) throws Exception {
+ public void testAddExportUndefinedModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}");
Path classes = base.resolve("classes");
@@ -89,7 +89,7 @@
}
@Test
- void testModuleSymbolOutterMostClass(Path base) throws Exception {
+ public void testModuleSymbolOutterMostClass(Path base) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
Path moduleSrc = base.resolve("module-src");
@@ -110,7 +110,7 @@
}
@Test
- void testParseEnterAnalyze(Path base) throws Exception {
+ public void testParseEnterAnalyze(Path base) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
Path moduleSrc = base.resolve("module-src");
@@ -148,7 +148,7 @@
}
@Test
- void testModuleImplicitModuleBoundaries(Path base) throws Exception {
+ public void testModuleImplicitModuleBoundaries(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1,
@@ -180,7 +180,7 @@
}
@Test
- void testAssignClassToAutomaticModule(Path base) throws Exception {
+ public void testAssignClassToAutomaticModule(Path base) throws Exception {
//check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not
//duplicated when being accessed through a classfile.
Path automaticSrc = base.resolve("automaticSrc");
@@ -239,7 +239,7 @@
}
@Test
- void testEmptyImplicitModuleInfo(Path base) throws Exception {
+ public void testEmptyImplicitModuleInfo(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
Files.createDirectories(src_m1);
@@ -269,4 +269,39 @@
}
+ @Test
+ public void testClassPackageClash(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path src_m1 = src.resolve("m1");
+ tb.writeJavaFiles(src_m1,
+ "module m1 { exports test.m1; }",
+ "package test.m1;\n" +
+ "public class Test {}\n");
+ Path src_m2 = src.resolve("m2");
+ tb.writeJavaFiles(src_m2,
+ "module m2 { requires m1; }",
+ "package test;\n" +
+ "public class m1 {}\n");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List<String> log = new JavacTask(tb)
+ .options("-modulesourcepath", src.toString(),
+ "-XDrawDiagnostics")
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> expected = Arrays.asList(
+ "m1.java:2:8: compiler.err.clash.with.pkg.of.same.name: kindname.class, test.m1",
+ "1 error"
+ );
+
+ if (!expected.equals(log)) {
+ throw new IllegalStateException(log.toString());
+ }
+ }
+
}
--- a/langtools/test/tools/javac/modules/GraphsTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/GraphsTest.java Fri May 06 06:23:30 2016 -0700
@@ -28,7 +28,8 @@
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder
+ * ModuleTestBase
* @run main GraphsTest
*/
@@ -41,6 +42,7 @@
import toolbox.JarTask;
import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
import toolbox.Task;
import toolbox.ToolBox;
@@ -69,11 +71,11 @@
*
*/
@Test
- void diamond(Path base) throws Exception {
+ public void diamond(Path base) throws Exception {
Path modules = Files.createDirectories(base.resolve("modules"));
- new ModuleBuilder("J")
+ new ModuleBuilder(tb, "J")
.exports("openJ")
.classes("package openJ; public class J { }")
.classes("package closedJ; public class J { }")
@@ -87,25 +89,25 @@
.run()
.writeAll();
- new ModuleBuilder("O")
+ new ModuleBuilder(tb, "O")
.exports("openO")
.requiresPublic("J", jarModules)
.classes("package openO; public class O { openJ.J j; }")
.classes("package closedO; public class O { }")
.build(modules);
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.requiresPublic("O", modules, jarModules)
.exports("openN")
.classes("package openN; public class N { }")
.classes("package closedN; public class N { }")
.build(modules);
- new ModuleBuilder("L")
+ new ModuleBuilder(tb, "L")
.requiresPublic("O", modules, jarModules)
.exports("openL")
.classes("package openL; public class L { }")
.classes("package closedL; public class L { }")
.build(modules);
- ModuleBuilder m = new ModuleBuilder("M");
+ ModuleBuilder m = new ModuleBuilder(tb, "M");
//positive case
Path positiveSrc = m
.requires("N", modules)
@@ -178,14 +180,14 @@
@Test
public void reexportOfQualifiedExport(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("M")
+ new ModuleBuilder(tb, "M")
.requiresPublic("N")
.write(modules);
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.exportsTo("pack", "M")
.classes("package pack; public class Clazz { }")
.write(modules);
- new ModuleBuilder("L")
+ new ModuleBuilder(tb, "L")
.requires("M")
.classes("package p; public class A { A(pack.Clazz cl){} } ")
.write(modules);
--- a/langtools/test/tools/javac/modules/HelloWorldTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/HelloWorldTest.java Fri May 06 06:23:30 2016 -0700
@@ -58,7 +58,7 @@
+ HELLO_WORLD;
@Test
- void testLegacyMode(Path base) throws Exception {
+ public void testLegacyMode(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, HELLO_WORLD);
@@ -85,7 +85,7 @@
}
@Test
- void testUnnamedModule(Path base) throws Exception {
+ public void testUnnamedModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, HELLO_WORLD);
@@ -101,7 +101,7 @@
}
@Test
- void testSingleModule(Path base) throws Exception {
+ public void testSingleModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeFile(src.resolve("module-info.java"), "module m { }");
tb.writeJavaFiles(src, PKG_HELLO_WORLD);
@@ -121,7 +121,7 @@
}
@Test
- void testModuleSourcePath(Path base) throws Exception {
+ public void testModuleSourcePath(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
--- a/langtools/test/tools/javac/modules/MOptionTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/MOptionTest.java Fri May 06 06:23:30 2016 -0700
@@ -47,7 +47,7 @@
}
@Test
- void testOneModule(Path base) throws Exception {
+ public void testOneModule(Path base) throws Exception {
Path src = base.resolve("src");
Path m1 = src.resolve("m1");
Path build = base.resolve("build");
@@ -112,7 +112,7 @@
}
@Test
- void testNoOutputDir(Path base) throws Exception {
+ public void testNoOutputDir(Path base) throws Exception {
Path src = base.resolve("src");
Path m1 = src.resolve("m1");
Path build = base.resolve("build");
@@ -135,7 +135,7 @@
}
@Test
- void testNoModuleSourcePath(Path base) throws Exception {
+ public void testNoModuleSourcePath(Path base) throws Exception {
Path src = base.resolve("src");
Path m1 = src.resolve("m1");
Path build = base.resolve("build");
@@ -158,7 +158,7 @@
}
@Test
- void testMultiModule(Path base) throws Exception {
+ public void testMultiModule(Path base) throws Exception {
Path src = base.resolve("src");
Path m1 = src.resolve("m1");
Path m2 = src.resolve("m2");
--- a/langtools/test/tools/javac/modules/ModuleFinderTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModuleFinderTest.java Fri May 06 06:23:30 2016 -0700
@@ -48,7 +48,7 @@
}
@Test
- void testDuplicateModulesOnPath(Path base) throws Exception {
+ public void testDuplicateModulesOnPath(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m1 { }");
--- a/langtools/test/tools/javac/modules/ModuleInfoTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModuleInfoTest.java Fri May 06 06:23:30 2016 -0700
@@ -51,7 +51,7 @@
* Check error message if module declaration not in module-info.java.
*/
@Test
- void testModuleDeclNotInModuleJava(Path base) throws Exception {
+ public void testModuleDeclNotInModuleJava(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeFile(src.resolve("M.java"), "module M { }");
String log = new JavacTask(tb)
@@ -69,7 +69,7 @@
* Verify that a package private class can be put in module-info.java.
*/
@Test
- void testNotModuleDeclInModuleJava_1(Path base) throws Exception {
+ public void testNotModuleDeclInModuleJava_1(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeFile(src.resolve("module-info.java"), "class C { }");
new JavacTask(tb)
@@ -83,7 +83,7 @@
* Verify that a public class cannot be put in module-info.java.
*/
@Test
- void testNotModuleDeclInModuleJava_2(Path base) throws Exception {
+ public void testNotModuleDeclInModuleJava_2(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeFile(src.resolve("module-info.java"), "public class C { }");
String log = new JavacTask(tb)
@@ -101,7 +101,7 @@
* Verify that only one module decl can be put in module-info.java.
*/
@Test
- void testSingleModuleDecl(Path base) throws Exception {
+ public void testSingleModuleDecl(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module M1 { } /*...*/ module M2 { }");
String log = new JavacTask(tb)
@@ -119,7 +119,7 @@
* Verify that missing requires are reported.
*/
@Test
- void testRequiresNotFound(Path base) throws Exception {
+ public void testRequiresNotFound(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module M1 { requires M2; }");
String log = new JavacTask(tb)
@@ -137,7 +137,7 @@
* Verify that missing exports are reported.
*/
@Test
- void testExportsNotFound(Path base) throws Exception {
+ public void testExportsNotFound(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module M1 { exports p to M2; }");
String log = new JavacTask(tb)
@@ -155,7 +155,7 @@
* Verify that a simple loop is detected.
*/
@Test
- void testRequiresSelf(Path base) throws Exception {
+ public void testRequiresSelf(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module M { requires M; }");
String log = new JavacTask(tb)
@@ -173,7 +173,7 @@
* Verify that a multi-module loop is detected.
*/
@Test
- void testRequiresLoop(Path base) throws Exception {
+ public void testRequiresLoop(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
@@ -201,7 +201,7 @@
* Verify that a multi-module loop is detected.
*/
@Test
- void testRequiresPublicLoop(Path base) throws Exception {
+ public void testRequiresPublicLoop(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
@@ -229,7 +229,7 @@
* Verify that duplicate requires are detected.
*/
@Test
- void testDuplicateRequires(Path base) throws Exception {
+ public void testDuplicateRequires(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
@@ -255,7 +255,7 @@
* Verify that duplicate exported packages are detected.
*/
@Test
- void testDuplicateExports_packages(Path base) throws Exception {
+ public void testDuplicateExports_packages(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m1 { exports p; exports p; }");
@@ -278,7 +278,7 @@
* Verify that duplicate exported packages are detected.
*/
@Test
- void testDuplicateExports_packages2(Path base) throws Exception {
+ public void testDuplicateExports_packages2(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports p to m2; }");
tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
@@ -302,7 +302,7 @@
* Verify that duplicate exported packages are detected.
*/
@Test
- void testDuplicateExports_modules(Path base) throws Exception {
+ public void testDuplicateExports_modules(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
--- a/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java Fri May 06 06:23:30 2016 -0700
@@ -61,7 +61,7 @@
}
@Test
- void testTreePathForModuleDecl(Path base) throws Exception {
+ public void testTreePathForModuleDecl(Path base) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
--- a/langtools/test/tools/javac/modules/ModulePathTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModulePathTest.java Fri May 06 06:23:30 2016 -0700
@@ -30,7 +30,8 @@
* jdk.compiler/com.sun.tools.javac.main
* jdk.jdeps/com.sun.tools.javap
* jdk.jlink/jdk.tools.jmod
- * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder
+ * ModuleTestBase
* @run main ModulePathTest
*/
@@ -41,6 +42,7 @@
import toolbox.JarTask;
import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
import toolbox.Task;
import toolbox.ToolBox;
@@ -54,7 +56,7 @@
}
@Test
- void testNotExistsOnPath(Path base) throws Exception {
+ public void testNotExistsOnPath(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "class C { }");
@@ -71,7 +73,7 @@
}
@Test
- void testNotADirOnPath_1(Path base) throws Exception {
+ public void testNotADirOnPath_1(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "class C { }");
tb.writeFile("dummy.txt", "");
@@ -89,7 +91,7 @@
}
@Test
- void testNotADirOnPath_2(Path base) throws Exception {
+ public void testNotADirOnPath_2(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "class C { }");
tb.writeFile("dummy.jimage", "");
@@ -107,7 +109,7 @@
}
@Test
- void testExplodedModuleOnPath(Path base) throws Exception {
+ public void testExplodedModuleOnPath(Path base) throws Exception {
Path modSrc = base.resolve("modSrc");
tb.writeJavaFiles(modSrc,
"module m1 { exports p; }",
@@ -137,7 +139,7 @@
}
@Test
- void testBadExplodedModuleOnPath(Path base) throws Exception {
+ public void testBadExplodedModuleOnPath(Path base) throws Exception {
Path modClasses = base.resolve("modClasses");
tb.writeFile(modClasses.resolve("module-info.class"), "module m1 { }");
@@ -162,7 +164,7 @@
}
@Test
- void testAutoJarOnPath(Path base) throws Exception {
+ public void testAutoJarOnPath(Path base) throws Exception {
Path jarSrc = base.resolve("jarSrc");
tb.writeJavaFiles(jarSrc,
"package p; public class CC { }");
@@ -195,7 +197,7 @@
}
@Test
- void testModJarOnPath(Path base) throws Exception {
+ public void testModJarOnPath(Path base) throws Exception {
Path jarSrc = base.resolve("jarSrc");
tb.writeJavaFiles(jarSrc,
"module m1 { exports p; }",
@@ -231,7 +233,7 @@
}
@Test
- void testBadJarOnPath(Path base) throws Exception {
+ public void testBadJarOnPath(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "class C { }");
tb.writeFile("dummy.jar", "");
@@ -249,7 +251,7 @@
}
@Test
- void testJModOnPath(Path base) throws Exception {
+ public void testJModOnPath(Path base) throws Exception {
Path jmodSrc = base.resolve("jmodSrc");
tb.writeJavaFiles(jmodSrc,
"module m1 { exports p; }",
@@ -282,7 +284,7 @@
}
@Test
- void testBadJModOnPath(Path base) throws Exception {
+ public void testBadJModOnPath(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "class C { }");
tb.writeFile("dummy.jmod", "");
@@ -300,9 +302,9 @@
}
@Test
- void relativePath(Path base) throws Exception {
+ public void relativePath(Path base) throws Exception {
final Path modules = base.resolve("modules");
- new ModuleBuilder("m1").build(modules);
+ new ModuleBuilder(tb, "m1").build(modules);
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
@@ -316,9 +318,9 @@
}
@Test
- void duplicatePaths_1(Path base) throws Exception {
+ public void duplicatePaths_1(Path base) throws Exception {
final Path modules = base.resolve("modules");
- new ModuleBuilder("m1").build(modules);
+ new ModuleBuilder(tb, "m1").build(modules);
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
@@ -332,9 +334,9 @@
}
@Test
- void duplicatePaths_2(Path base) throws Exception {
+ public void duplicatePaths_2(Path base) throws Exception {
final Path modules = base.resolve("modules");
- new ModuleBuilder("m1").build(modules);
+ new ModuleBuilder(tb, "m1").build(modules);
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
@@ -349,15 +351,15 @@
}
@Test
- void oneModuleHidesAnother(Path base) throws Exception {
+ public void oneModuleHidesAnother(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
final Path deepModuleDir = module.resolve("deepModuleDir");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class E { }")
.build(deepModuleDir);
@@ -374,19 +376,19 @@
}
@Test
- void modulesInDifferentContainers(Path base) throws Exception {
+ public void modulesInDifferentContainers(Path base) throws Exception {
final Path modules = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("one")
.classes("package one; public class A { }")
.build(modules);
- new ModuleBuilder("m2")
+ new ModuleBuilder(tb, "m2")
.requires("m1", modules)
.build(base.resolve("tmp"));
jar(base.resolve("tmp/m2"), modules.resolve("m2.jar"));
- new ModuleBuilder("m3")
+ new ModuleBuilder(tb, "m3")
.requires("m2", modules)
.build(base.resolve("tmp"));
jmod(base.resolve("tmp/m3"), modules.resolve("m3.jmod"));
--- a/langtools/test/tools/javac/modules/ModuleSourcePathTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java Fri May 06 06:23:30 2016 -0700
@@ -56,7 +56,7 @@
}
@Test
- void testSourcePathConflict(Path base) throws Exception {
+ public void testSourcePathConflict(Path base) throws Exception {
Path sp = base.resolve("src");
Path msp = base.resolve("srcmodules");
@@ -74,7 +74,7 @@
}
@Test
- void testUnnormalizedPath1(Path base) throws Exception {
+ public void testUnnormalizedPath1(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -91,7 +91,7 @@
}
@Test
- void testUnnormalizedPath2(Path base) throws Exception {
+ public void testUnnormalizedPath2(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -115,7 +115,7 @@
}
@Test
- void regularBraces(Path base) throws Exception {
+ public void regularBraces(Path base) throws Exception {
generateModules(base, "src1", "src2/inner_dir");
final Path modules = base.resolve("modules");
@@ -136,7 +136,7 @@
}
@Test
- void mismatchedBraces(Path base) throws Exception {
+ public void mismatchedBraces(Path base) throws Exception {
final List<String> sourcePaths = Arrays.asList(
"{",
"}",
@@ -165,7 +165,7 @@
}
@Test
- void deepBraces(Path base) throws Exception {
+ public void deepBraces(Path base) throws Exception {
String[] modulePaths = {"src/src1",
"src/src2",
"src/src3",
@@ -197,7 +197,7 @@
}
@Test
- void fileInPath(Path base) throws Exception {
+ public void fileInPath(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
tb.writeFile(base.resolve("dummy.txt"), "");
@@ -218,7 +218,7 @@
}
@Test
- void noAlternative(Path base) throws Exception {
+ public void noAlternative(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
@@ -238,7 +238,7 @@
}
@Test
- void noChoice(Path base) throws Exception {
+ public void noChoice(Path base) throws Exception {
tb.writeJavaFiles(base.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
final Path modules = base.resolve("modules");
@@ -257,7 +257,7 @@
}
@Test
- void nestedModules(Path src) throws Exception {
+ public void nestedModules(Path src) throws Exception {
Path carModule = src.resolve("car");
tb.writeJavaFiles(carModule, "module car { }", "package light; class Headlight { }");
tb.writeJavaFiles(carModule.resolve("engine"), "module engine { }", "package flat; class Piston { }");
@@ -277,7 +277,7 @@
}
@Test
- void relativePaths(Path base) throws Exception {
+ public void relativePaths(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("kettle"), "module kettle { }", "package electric; class Heater { }");
@@ -296,7 +296,7 @@
}
@Test
- void duplicatePaths(Path base) throws Exception {
+ public void duplicatePaths(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }");
@@ -315,7 +315,7 @@
}
@Test
- void notExistentPaths(Path base) throws Exception {
+ public void notExistentPaths(Path base) throws Exception {
tb.writeJavaFiles(base.resolve("m1"), "module m1 { requires m0; }", "package a; class A { }");
final Path modules = base.resolve("modules");
@@ -334,7 +334,7 @@
}
@Test
- void notExistentPathShouldBeSkipped(Path base) throws Exception {
+ public void notExistentPathShouldBeSkipped(Path base) throws Exception {
tb.writeJavaFiles(base.resolve("m1"), "module m1 { }", "package a; class A { }");
final Path modules = base.resolve("modules");
@@ -352,7 +352,7 @@
}
@Test
- void commas(Path base) throws Exception {
+ public void commas(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }");
@@ -371,7 +371,7 @@
}
@Test
- void asterisk(Path base) throws Exception {
+ public void asterisk(Path base) throws Exception {
tb.writeJavaFiles(base.resolve("kettle").resolve("classes"), "module kettle { }",
"package electric; class Heater { }");
@@ -391,7 +391,7 @@
}
@Test
- void asteriskInDifferentSets(Path base) throws Exception {
+ public void asteriskInDifferentSets(Path base) throws Exception {
Path src = base.resolve("src");
final Path module = src.resolve("kettle");
tb.writeJavaFiles(module.resolve("classes"), "module kettle { }", "package electric; class Heater { }");
@@ -417,7 +417,7 @@
}
@Test
- void asteriskIllegalUse(Path base) throws Exception {
+ public void asteriskIllegalUse(Path base) throws Exception {
final List<String> sourcePaths = Arrays.asList(
"*",
"**",
--- a/langtools/test/tools/javac/modules/ModuleTestBase.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModuleTestBase.java Fri May 06 06:23:30 2016 -0700
@@ -43,19 +43,20 @@
import java.util.stream.Collectors;
import toolbox.JavacTask;
+import toolbox.TestRunner;
import toolbox.ToolBox;
/**
* Base class for module tests.
*/
-public class ModuleTestBase {
+public class ModuleTestBase extends TestRunner {
protected ToolBox tb;
- protected PrintStream out;
private int errors;
- /** Marker annotation for test methods to be invoked by runTests. */
- @Retention(RetentionPolicy.RUNTIME)
- @interface Test { }
+ ModuleTestBase() {
+ super(System.err);
+ tb = new ToolBox();
+ }
/**
* Run all methods annotated with @Test, and throw an exception if any
@@ -63,47 +64,12 @@
*
* @throws Exception if any errors occurred
*/
- void runTests() throws Exception {
- if (tb == null)
- tb = new ToolBox();
- out = System.err;
-
- for (Method m: getClass().getDeclaredMethods()) {
- Annotation a = m.getAnnotation(Test.class);
- if (a != null) {
- try {
- out.println("Running test " + m.getName());
- Path baseDir = Paths.get(m.getName());
- m.invoke(this, new Object[] { baseDir });
- } catch (InvocationTargetException e) {
- Throwable cause = e.getCause();
- error("Exception: " + e.getCause());
- cause.printStackTrace(out);
- }
- out.println();
- }
- }
- if (errors > 0)
- throw new Exception(errors + " errors occurred");
+ protected void runTests() throws Exception {
+ runTests(m -> new Object[] { Paths.get(m.getName()) });
}
- // move to ToolBox?
- // change returntyp to List<Path> -- means updating ToolBox methods
Path[] findJavaFiles(Path... paths) throws IOException {
- Set<Path> files = new TreeSet<>();
- for (Path p : paths) {
- Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
- throws IOException {
- if (file.getFileName().toString().endsWith(".java")) {
- files.add(file);
- }
- return FileVisitResult.CONTINUE;
- }
- });
- }
- return files.toArray(new Path[files.size()]);
+ return tb.findJavaFiles(paths);
}
void error(String message) {
@@ -111,79 +77,4 @@
errors++;
}
- public class ModuleBuilder {
-
- private final String name;
- private String requires = "";
- private String exports = "";
- private String uses = "";
- private String provides = "";
- private String modulePath = "";
- private List<String> content = new ArrayList<>();
-
- public ModuleBuilder(String name) {
- this.name = name;
- }
-
- public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
- return requires("public " + requires, modulePath);
- }
-
- public ModuleBuilder requires(String requires, Path... modulePath) {
- this.requires += " requires " + requires + ";\n";
- this.modulePath += Arrays.stream(modulePath)
- .map(Path::toString)
- .collect(Collectors.joining(File.pathSeparator));
- return this;
- }
-
- public ModuleBuilder exportsTo(String pkg, String module) {
- return exports(pkg + " to " + module);
- }
-
- public ModuleBuilder exports(String pkg) {
- this.exports += " exports " + pkg + ";\n";
- return this;
- }
-
- public ModuleBuilder uses(String uses) {
- this.uses += " uses " + uses + ";\n";
- return this;
- }
-
- public ModuleBuilder provides(String service, String implementation) {
- this.provides += " provides " + service + " with " + implementation + ";\n";
- return this;
- }
-
- public ModuleBuilder classes(String... content) {
- this.content.addAll(Arrays.asList(content));
- return this;
- }
-
- public Path write(Path where) throws IOException {
- Files.createDirectories(where);
- List<String> sources = new ArrayList<>();
- sources.add("module " + name + "{"
- + requires
- + exports
- + uses
- + provides
- + "}");
- sources.addAll(content);
- Path moduleSrc = where.resolve(name + "/src");
- tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{}));
- return moduleSrc;
- }
-
- public void build(Path where) throws IOException {
- Path moduleSrc = write(where);
- new JavacTask(tb)
- .outdir(where.resolve(name))
- .options("-mp", modulePath)
- .files(findJavaFiles(moduleSrc))
- .run()
- .writeAll();
- }
- }
}
--- a/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java Fri May 06 06:23:30 2016 -0700
@@ -55,7 +55,7 @@
}
@Test
- void testModulesAndClassPath(Path base) throws Exception {
+ public void testModulesAndClassPath(Path base) throws Exception {
Path jar = prepareTestJar(base);
Path moduleSrc = base.resolve("module-src");
@@ -106,7 +106,7 @@
}
@Test
- void testImplicitSourcePathModuleInfo(Path base) throws Exception {
+ public void testImplicitSourcePathModuleInfo(Path base) throws Exception {
Path jar = prepareTestJar(base);
Path moduleSrc = base.resolve("module-src");
@@ -139,7 +139,7 @@
}
@Test
- void testModuleInfoFromOutput(Path base) throws Exception {
+ public void testModuleInfoFromOutput(Path base) throws Exception {
Path jar = prepareTestJar(base);
Path moduleSrc = base.resolve("module-src");
@@ -221,7 +221,7 @@
}
@Test
- void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception {
+ public void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
--- a/langtools/test/tools/javac/modules/MultiModuleModeTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/MultiModuleModeTest.java Fri May 06 06:23:30 2016 -0700
@@ -49,7 +49,7 @@
}
@Test
- void testDuplicateModules(Path base) throws Exception {
+ public void testDuplicateModules(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -72,7 +72,7 @@
}
@Test
- void testCantFindModule(Path base) throws Exception {
+ public void testCantFindModule(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -95,7 +95,7 @@
}
@Test
- void testModuleNameMismatch(Path base) throws Exception {
+ public void testModuleNameMismatch(Path base) throws Exception {
Path src = base.resolve("src");
Path src_m1 = src.resolve("m1");
tb.writeJavaFiles(src_m1, "module m2 { }");
@@ -116,7 +116,7 @@
}
@Test
- void testImplicitModuleSource(Path base) throws Exception {
+ public void testImplicitModuleSource(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
tb.writeJavaFiles(src.resolve("m2"), "module m2 { requires m1; }");
@@ -132,7 +132,7 @@
}
@Test
- void testImplicitModuleClass(Path base) throws Exception {
+ public void testImplicitModuleClass(Path base) throws Exception {
Path src1 = base.resolve("src1");
tb.writeJavaFiles(src1.resolve("m1"), "module m1 { }");
Path modules1 = base.resolve("modules1");
--- a/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java Fri May 06 06:23:30 2016 -0700
@@ -45,7 +45,7 @@
}
@Test
- void testCompileNoError(Path base) throws Exception {
+ public void testCompileNoError(Path base) throws Exception {
Path mod = base.resolve("mod");
tb.writeJavaFiles(mod, "module mod { exports pkg; }");
Path pkg = mod.resolve("pkg");
--- a/langtools/test/tools/javac/modules/NPEEmptyFileTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/NPEEmptyFileTest.java Fri May 06 06:23:30 2016 -0700
@@ -45,7 +45,7 @@
}
@Test
- void compileEmptyFile(Path base) throws Exception {
+ public void compileEmptyFile(Path base) throws Exception {
Path modules = base.resolve("modules");
Files.createDirectories(modules);
Path emptyJavaFile = base.resolve("Test.java");
--- a/langtools/test/tools/javac/modules/OutputDirTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/OutputDirTest.java Fri May 06 06:23:30 2016 -0700
@@ -60,7 +60,7 @@
}
@Test
- void testError(Path base) throws Exception {
+ public void testError(Path base) throws Exception {
String log = new JavacTask(tb)
.options("-XDrawDiagnostics",
"-modulesourcepath", src.toString())
@@ -74,7 +74,7 @@
}
@Test
- void testProcOnly(Path base) throws IOException {
+ public void testProcOnly(Path base) throws IOException {
new JavacTask(tb)
.options("-XDrawDiagnostics",
"-proc:only",
@@ -85,7 +85,7 @@
}
@Test
- void testClassOutDir(Path base) throws IOException {
+ public void testClassOutDir(Path base) throws IOException {
Path classes = base.resolve("classes");
new JavacTask(tb)
.options("-XDrawDiagnostics",
@@ -97,7 +97,7 @@
}
@Test
- void testExplodedOutDir(Path base) throws Exception {
+ public void testExplodedOutDir(Path base) throws Exception {
Path modSrc = base.resolve("modSrc");
tb.writeJavaFiles(modSrc,
"module m1 { exports p; }",
@@ -131,7 +131,7 @@
}
@Test
- void testInExplodedOutDir(Path base) throws Exception {
+ public void testInExplodedOutDir(Path base) throws Exception {
Path modSrc = base.resolve("modSrc");
tb.writeJavaFiles(modSrc,
"module m1 { exports p; }",
--- a/langtools/test/tools/javac/modules/PackageConflictTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/PackageConflictTest.java Fri May 06 06:23:30 2016 -0700
@@ -28,7 +28,7 @@
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
* @run main PackageConflictTest
*/
@@ -38,6 +38,7 @@
import java.util.List;
import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
import toolbox.Task;
import toolbox.ToolBox;
@@ -48,7 +49,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"package java.util; public class MyList { }");
@@ -68,7 +69,7 @@
}
@Test
- void testDisjoint(Path base) throws Exception {
+ public void testDisjoint(Path base) throws Exception {
Path m1 = base.resolve("m1");
Path m2 = base.resolve("m2");
tb.writeJavaFiles(m1,
@@ -89,7 +90,7 @@
}
@Test
- void testConflictInDependencies(Path base) throws Exception {
+ public void testConflictInDependencies(Path base) throws Exception {
Path m1 = base.resolve("m1");
Path m2 = base.resolve("m2");
Path m3 = base.resolve("m3");
@@ -123,13 +124,13 @@
}
@Test
- void testSimple2(Path base) throws Exception {
+ public void testSimple2(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.exports("pack")
.classes("package pack; public class A { }")
.build(modules);
- new ModuleBuilder("M")
+ new ModuleBuilder(tb, "M")
.requires("N")
.classes("package pack; public class B { pack.A f; }")
.write(modules);
@@ -147,14 +148,14 @@
}
@Test
- void testPrivateConflict(Path base) throws Exception {
+ public void testPrivateConflict(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.exports("publ")
.classes("package pack; public class A { }")
.classes("package publ; public class B { }")
.write(modules);
- new ModuleBuilder("M")
+ new ModuleBuilder(tb, "M")
.requires("N")
.classes("package pack; public class C { publ.B b; }")
.write(modules);
@@ -173,14 +174,14 @@
}
@Test
- void testPrivateConflictOnModulePath(Path base) throws Exception {
+ public void testPrivateConflictOnModulePath(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.exports("publ")
.classes("package pack; public class A { }")
.classes("package publ; public class B { }")
.build(modules);
- new ModuleBuilder("M")
+ new ModuleBuilder(tb, "M")
.requires("N")
.classes("package pack; public class C { publ.B b; }")
.write(modules);
@@ -199,17 +200,17 @@
}
@Test
- void testRequiresConflictExports(Path base) throws Exception {
+ public void testRequiresConflictExports(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("M")
+ new ModuleBuilder(tb, "M")
.exports("pack")
.classes("package pack; public class A { }")
.build(modules);
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.exports("pack")
.classes("package pack; public class B { }")
.build(modules);
- new ModuleBuilder("K")
+ new ModuleBuilder(tb, "K")
.requires("M")
.requires("N")
.classes("package pkg; public class C { pack.A a; pack.B b; }")
@@ -231,18 +232,18 @@
}
@Test
- void testQulifiedExportsToDifferentModules(Path base) throws Exception {
+ public void testQulifiedExportsToDifferentModules(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("U").write(modules);
- new ModuleBuilder("M")
+ new ModuleBuilder(tb, "U").write(modules);
+ new ModuleBuilder(tb, "M")
.exports("pkg to U")
.classes("package pkg; public class A { public static boolean flagM; }")
.write(modules);
- new ModuleBuilder("N")
+ new ModuleBuilder(tb, "N")
.exports("pkg to K")
.classes("package pkg; public class A { public static boolean flagN; }")
.write(modules);
- ModuleBuilder moduleK = new ModuleBuilder("K");
+ ModuleBuilder moduleK = new ModuleBuilder(tb, "K");
moduleK.requires("M")
.requires("N")
.classes("package p; public class DependsOnN { boolean f = pkg.A.flagN; } ")
--- a/langtools/test/tools/javac/modules/PackageMultipleModules.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/PackageMultipleModules.java Fri May 06 06:23:30 2016 -0700
@@ -49,7 +49,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path m1 = base.resolve("m1");
Path m2 = base.resolve("m2");
tb.writeJavaFiles(m1,
--- a/langtools/test/tools/javac/modules/PluginsInModulesTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/PluginsInModulesTest.java Fri May 06 06:23:30 2016 -0700
@@ -127,7 +127,7 @@
Path classes;
@Test
- void testUseOnlyOneProcessor(Path base) throws Exception {
+ public void testUseOnlyOneProcessor(Path base) throws Exception {
initialization(base);
List<String> log = new JavacTask(tb)
.options("-processormodulepath", processorCompiledModules.toString(),
--- a/langtools/test/tools/javac/modules/ProvidesTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ProvidesTest.java Fri May 06 06:23:30 2016 -0700
@@ -48,7 +48,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2; }",
@@ -65,7 +65,7 @@
}
@Test
- void testMulti(Path base) throws Exception {
+ public void testMulti(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p1; }",
@@ -86,7 +86,7 @@
}
@Test
- void testMissingWith(Path base) throws Exception {
+ public void testMissingWith(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p.C; }",
@@ -108,7 +108,7 @@
}
@Test
- void testDuplicateProvides(Path base) throws Exception {
+ public void testDuplicateProvides(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
@@ -126,7 +126,7 @@
}
@Test
- void testMissingService(Path base) throws Exception {
+ public void testMissingService(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p.Missing with p.C; }",
@@ -151,7 +151,7 @@
}
@Test
- void testProvidesFromAnotherModule(Path base) throws Exception {
+ public void testProvidesFromAnotherModule(Path base) throws Exception {
Path modules = base.resolve("modules");
tb.writeJavaFiles(modules.resolve("M"),
"module M { exports p; }",
@@ -177,7 +177,7 @@
}
@Test
- void testServiceIsNotImplemented(Path base) throws Exception {
+ public void testServiceIsNotImplemented(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p.A with p.B; }",
@@ -200,7 +200,7 @@
}
@Test
- void testMissingImplementation(Path base) throws Exception {
+ public void testMissingImplementation(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p.C with p.Impl; }",
@@ -222,7 +222,7 @@
}
@Test
- void testSeveralImplementations(Path base) throws Exception {
+ public void testSeveralImplementations(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }",
@@ -238,7 +238,7 @@
}
@Test
- void testOneImplementationsForServices(Path base) throws Exception {
+ public void testOneImplementationsForServices(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }",
@@ -254,7 +254,7 @@
}
@Test
- void testAbstractImplementation(Path base) throws Exception {
+ public void testAbstractImplementation(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2; }",
@@ -277,7 +277,7 @@
}
@Test
- void testInterfaceImplementation(Path base) throws Exception {
+ public void testInterfaceImplementation(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.Service with p2.Impl; }",
@@ -300,7 +300,7 @@
}
@Test
- void testProtectedImplementation(Path base) throws Exception {
+ public void testProtectedImplementation(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2; }",
@@ -323,7 +323,7 @@
}
@Test
- void testNoNoArgConstructor(Path base) throws Exception {
+ public void testNoNoArgConstructor(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p1.C1; provides p1.C1 with p2.C2; }",
@@ -346,7 +346,7 @@
}
@Test
- void testPrivateNoArgConstructor(Path base) throws Exception {
+ public void testPrivateNoArgConstructor(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p1.C1; provides p1.C1 with p2.C2; }",
@@ -369,7 +369,7 @@
}
@Test
- void testServiceIndirectlyImplemented(Path base) throws Exception {
+ public void testServiceIndirectlyImplemented(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C3; }",
@@ -385,7 +385,7 @@
}
@Test
- void testServiceImplementationInnerClass(Path base) throws Exception {
+ public void testServiceImplementationInnerClass(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2.Inner; }",
@@ -408,7 +408,7 @@
}
@Test
- void testServiceDefinitionInnerClass(Path base) throws Exception {
+ public void testServiceDefinitionInnerClass(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1.InnerDefinition with p2.C2; }",
--- a/langtools/test/tools/javac/modules/QueryBeforeEnter.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/QueryBeforeEnter.java Fri May 06 06:23:30 2016 -0700
@@ -65,7 +65,7 @@
}
@Test
- void testEmpty(Path base) throws Exception {
+ public void testEmpty(Path base) throws Exception {
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
com.sun.source.util.JavacTask task =
(com.sun.source.util.JavacTask) javaCompiler.getTask(null, null, null, null, null, null);
@@ -75,7 +75,7 @@
}
@Test
- void testUnnamed(Path base) throws Exception {
+ public void testUnnamed(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
@@ -151,7 +151,7 @@
}
@Test
- void testSingleNamed(Path base) throws Exception {
+ public void testSingleNamed(Path base) throws Exception {
Path moduleSrc = base.resolve("module-src");
Path m1 = moduleSrc.resolve("m1");
@@ -226,7 +226,7 @@
}
@Test
- void testMultiModule(Path base) throws Exception {
+ public void testMultiModule(Path base) throws Exception {
Path modulePathSrc = base.resolve("module-path-src");
Path m1 = modulePathSrc.resolve("m1");
@@ -311,7 +311,7 @@
}
@Test
- void testTooSoon(Path base) throws Exception {
+ public void testTooSoon(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
--- a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java Fri May 06 06:23:30 2016 -0700
@@ -46,7 +46,7 @@
}
@Test
- void testDuplicateUses(Path base) throws Exception {
+ public void testDuplicateUses(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p1.C1; uses p1.C1; }",
@@ -66,7 +66,7 @@
}
@Test
- void testDuplicateProvides(Path base) throws Exception {
+ public void testDuplicateProvides(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
--- a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java Fri May 06 06:23:30 2016 -0700
@@ -46,7 +46,7 @@
}
@Test
- void testExportUnknownPackage(Path base) throws Exception {
+ public void testExportUnknownPackage(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m { exports p1; }");
Path classes = base.resolve("classes");
@@ -64,7 +64,7 @@
}
@Test
- void testExportEmptyPackage(Path base) throws Exception {
+ public void testExportEmptyPackage(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { exports p1; }",
@@ -84,7 +84,7 @@
}
@Test
- void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception {
+ public void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "module m { exports p1; }");
Path p1 = src.resolve("p1");
--- a/langtools/test/tools/javac/modules/RequiresPublicTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/RequiresPublicTest.java Fri May 06 06:23:30 2016 -0700
@@ -47,7 +47,7 @@
}
@Test
- void testJavaSE_OK(Path base) throws Exception {
+ public void testJavaSE_OK(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { requires java.se; }",
@@ -66,7 +66,7 @@
}
@Test
- void testJavaSE_Fail(Path base) throws Exception {
+ public void testJavaSE_Fail(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { requires java.se; }",
@@ -90,7 +90,7 @@
}
@Test
- void testComplex_OK(Path base) throws Exception {
+ public void testComplex_OK(Path base) throws Exception {
Path src = getComplexSrc(base, "", "");
Path classes = base.resolve("classes");
Files.createDirectories(classes);
@@ -104,7 +104,7 @@
}
@Test
- void testComplex_Fail(Path base) throws Exception {
+ public void testComplex_Fail(Path base) throws Exception {
Path src = getComplexSrc(base,
"import p5.C5; import p6.C6; import p7.C7;\n",
"C5 c5; C6 c6; C7 c7;\n");
--- a/langtools/test/tools/javac/modules/ResolveTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ResolveTest.java Fri May 06 06:23:30 2016 -0700
@@ -45,7 +45,7 @@
}
@Test
- void testMissingSimpleTypeUnnamedModule(Path base) throws Exception {
+ public void testMissingSimpleTypeUnnamedModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "class C { D d; }");
@@ -62,7 +62,7 @@
}
@Test
- void testMissingSimpleTypeNamedModule(Path base) throws Exception {
+ public void testMissingSimpleTypeNamedModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { }",
@@ -81,7 +81,7 @@
}
@Test
- void testUnexportedTypeUnreadableModule(Path base) throws Exception {
+ public void testUnexportedTypeUnreadableModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { }",
@@ -105,7 +105,7 @@
}
@Test
- void testUnexportedTypeReadableModule(Path base) throws Exception {
+ public void testUnexportedTypeReadableModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { }",
@@ -129,7 +129,7 @@
}
@Test
- void testQualifiedExportedTypeReadableModule(Path base) throws Exception {
+ public void testQualifiedExportedTypeReadableModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p1 to m3; }",
@@ -155,7 +155,7 @@
}
@Test
- void testExportedTypeUnreadableModule(Path base) throws Exception {
+ public void testExportedTypeUnreadableModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p1; }",
@@ -179,7 +179,7 @@
}
@Test
- void testExportedTypeReadableModule(Path base) throws Exception {
+ public void testExportedTypeReadableModule(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p1; }",
@@ -199,7 +199,7 @@
}
@Test
- void testExportedTypeReadableModule2(Path base) throws Exception {
+ public void testExportedTypeReadableModule2(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p1 to m2; }",
--- a/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java Fri May 06 06:23:30 2016 -0700
@@ -48,7 +48,7 @@
}
@Test
- void testError(Path base) throws Exception {
+ public void testError(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.I with p1.Outer.A; }",
--- a/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java Fri May 06 06:23:30 2016 -0700
@@ -49,7 +49,7 @@
}
@Test
- void testWarning(Path base) throws Exception {
+ public void testWarning(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { provides p1.C1 with p2.C2; }",
@@ -76,7 +76,7 @@
}
@Test
- void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception {
+ public void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p1; }",
--- a/langtools/test/tools/javac/modules/SingleModuleModeTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/SingleModuleModeTest.java Fri May 06 06:23:30 2016 -0700
@@ -59,7 +59,7 @@
}
@Test
- void testTooManyModules(Path base) throws Exception {
+ public void testTooManyModules(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
@@ -76,7 +76,7 @@
}
@Test
- void testImplicitModuleSource(Path base) throws Exception {
+ public void testImplicitModuleSource(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { }",
@@ -90,7 +90,7 @@
}
@Test
- void testImplicitModuleClass(Path base) throws Exception {
+ public void testImplicitModuleClass(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { }",
@@ -112,7 +112,7 @@
}
@Test
- void testImplicitModuleClassAP(Path base) throws Exception {
+ public void testImplicitModuleClassAP(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses java.lang.Runnable; }",
@@ -137,7 +137,7 @@
}
@Test
- void testImplicitModuleSourceAP(Path base) throws Exception {
+ public void testImplicitModuleSourceAP(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses java.lang.Runnable; }",
--- a/langtools/test/tools/javac/modules/SubpackageTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/SubpackageTest.java Fri May 06 06:23:30 2016 -0700
@@ -52,7 +52,7 @@
}
@Test // based on JDK-8075435
- void testUnnamedModule(Path base) throws Exception {
+ public void testUnnamedModule(Path base) throws Exception {
Path libsrc = base.resolve("lib/src");
tb.writeJavaFiles(libsrc,
"package p; public class E extends Error { }");
@@ -83,7 +83,7 @@
}
@Test
- void testSimpleMulti(Path base) throws Exception {
+ public void testSimpleMulti(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("mp"),
"module mp { exports p; }",
--- a/langtools/test/tools/javac/modules/UpgradeModulePathTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/UpgradeModulePathTest.java Fri May 06 06:23:30 2016 -0700
@@ -28,7 +28,7 @@
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
* @run main UpgradeModulePathTest
*/
@@ -36,6 +36,7 @@
import java.nio.file.Path;
import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
import toolbox.Task;
import toolbox.ToolBox;
@@ -47,15 +48,15 @@
}
@Test
- void simpleUsage(Path base) throws Exception {
+ public void simpleUsage(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
final Path upgradeModule = base.resolve("upgradeModule");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class E { }")
.build(upgradeModule);
@@ -73,15 +74,15 @@
}
@Test
- void onlyUpgradeModulePath(Path base) throws Exception {
+ public void onlyUpgradeModulePath(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
final Path upgradeModule = base.resolve("upgradeModule");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class E { }")
.build(upgradeModule);
@@ -98,15 +99,15 @@
}
@Test
- void withModuleSourcePath(Path base) throws Exception {
+ public void withModuleSourcePath(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
final Path upgradeModule = base.resolve("upgradeModule");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class E { }")
.build(upgradeModule);
@@ -115,7 +116,7 @@
tb.writeJavaFiles(s.resolve("m3"), "module m3 { }");
final Path upgradeModule3 = base.resolve("upgradeModule");
- new ModuleBuilder("m3")
+ new ModuleBuilder(tb, "m3")
.exports("pkg3")
.classes("package pkg3; public class E { }")
.build(upgradeModule);
@@ -135,15 +136,15 @@
}
@Test
- void sameUpgradeAndModulePath(Path base) throws Exception {
+ public void sameUpgradeAndModulePath(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
final Path upgradeModule = base.resolve("upgradeModule");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class E { }")
.build(upgradeModule);
@@ -161,9 +162,9 @@
}
@Test
- void dummyFileInUpgradeModulePath(Path base) throws Exception {
+ public void dummyFileInUpgradeModulePath(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
@@ -189,24 +190,24 @@
}
@Test
- void severalUpgradeModules(Path base) throws Exception {
+ public void severalUpgradeModules(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class A { }")
.build(module);
- new ModuleBuilder("m2")
+ new ModuleBuilder(tb, "m2")
.exports("pkg2")
.classes("package pkg2; public class B { }")
.build(module);
Path upgradeModule = base.resolve("upgradeModule");
- new ModuleBuilder("m2")
+ new ModuleBuilder(tb, "m2")
.exports("pkg2")
.classes("package pkg2; public class BC { }")
.build(upgradeModule);
- new ModuleBuilder("m3")
+ new ModuleBuilder(tb, "m3")
.exports("pkg3")
.classes("package pkg3; public class DC { }")
.build(upgradeModule);
@@ -240,21 +241,21 @@
}
@Test
- void severalUpgradeModulePathsLastWin(Path base) throws Exception {
+ public void severalUpgradeModulePathsLastWin(Path base) throws Exception {
final Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class E { }")
.build(module);
final Path upgradeModule1 = base.resolve("upgradeModule1");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class EC1 { }")
.build(upgradeModule1);
final Path upgradeModule2 = base.resolve("upgradeModule2");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("pkg2")
.classes("package pkg2; public class EC2 { }")
.build(upgradeModule2);
--- a/langtools/test/tools/javac/modules/UsesTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/UsesTest.java Fri May 06 06:23:30 2016 -0700
@@ -28,7 +28,7 @@
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
* @run main UsesTest
*/
@@ -39,6 +39,7 @@
import java.util.List;
import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
import toolbox.Task;
import toolbox.ToolBox;
@@ -49,7 +50,7 @@
}
@Test
- void testSimple(Path base) throws Exception {
+ public void testSimple(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p.C; }",
@@ -65,7 +66,7 @@
}
@Test
- void testSimpleInner(Path base) throws Exception {
+ public void testSimpleInner(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p.C.Inner; }",
@@ -81,7 +82,7 @@
}
@Test
- void testSimpleAnnotation(Path base) throws Exception {
+ public void testSimpleAnnotation(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p.C; }",
@@ -97,7 +98,7 @@
}
@Test
- void testPrivateService(Path base) throws Exception {
+ public void testPrivateService(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p.C.A; uses p.C; }",
@@ -119,7 +120,7 @@
}
@Test
- void testMulti(Path base) throws Exception {
+ public void testMulti(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { exports p; }",
@@ -138,13 +139,13 @@
}
@Test
- void testMultiOnModulePath(Path base) throws Exception {
+ public void testMultiOnModulePath(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("p")
.classes("package p; public class C { }")
.build(modules);
- new ModuleBuilder("m2")
+ new ModuleBuilder(tb, "m2")
.requires("m1")
.uses("p.C")
.write(modules);
@@ -158,13 +159,13 @@
}
@Test
- void testMultiOnModulePathInner(Path base) throws Exception {
+ public void testMultiOnModulePathInner(Path base) throws Exception {
Path modules = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.exports("p")
.classes("package p; public class C { public class Inner { } }")
.build(modules);
- new ModuleBuilder("m2")
+ new ModuleBuilder(tb, "m2")
.requires("m1")
.uses("p.C.Inner")
.write(modules);
@@ -178,7 +179,7 @@
}
@Test
- void testDuplicateUses(Path base) throws Exception {
+ public void testDuplicateUses(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m"),
"module m { uses p.C; uses p.C; }",
@@ -199,7 +200,7 @@
}
@Test
- void testServiceNotExist(Path base) throws Exception {
+ public void testServiceNotExist(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { uses p.NotExist; }",
@@ -220,7 +221,7 @@
}
@Test
- void testUsesUnexportedService(Path base) throws Exception {
+ public void testUsesUnexportedService(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { }",
@@ -244,7 +245,7 @@
}
@Test
- void testUsesUnexportedButProvidedService(Path base) throws Exception {
+ public void testUsesUnexportedButProvidedService(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src.resolve("m1"),
"module m1 { provides p.C with p.C; }",
--- a/langtools/test/tools/javac/modules/XModuleTest.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/javac/modules/XModuleTest.java Fri May 06 06:23:30 2016 -0700
@@ -28,7 +28,7 @@
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
* @run main XModuleTest
*/
@@ -37,7 +37,9 @@
import java.util.List;
import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
import toolbox.Task;
+import toolbox.TestRunner;
import toolbox.ToolBox;
public class XModuleTest extends ModuleTestBase {
@@ -47,7 +49,7 @@
}
@Test
- void testCorrectXModule(Path base) throws Exception {
+ public void testCorrectXModule(Path base) throws Exception {
//note: avoiding use of java.base, as that gets special handling on some places:
Path src = base.resolve("src");
tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
@@ -67,7 +69,7 @@
}
@Test
- void testSourcePath(Path base) throws Exception {
+ public void testSourcePath(Path base) throws Exception {
//note: avoiding use of java.base, as that gets special handling on some places:
Path src = base.resolve("src");
tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element, Other { }", "package javax.lang.model.element; interface Other { }");
@@ -87,7 +89,7 @@
}
@Test
- void testClassPath(Path base) throws Exception {
+ public void testClassPath(Path base) throws Exception {
Path cpSrc = base.resolve("cpSrc");
tb.writeJavaFiles(cpSrc, "package p; public interface Other { }");
Path cpClasses = base.resolve("cpClasses");
@@ -122,7 +124,7 @@
}
@Test
- void testNoModuleInfoOnSourcePath(Path base) throws Exception {
+ public void testNoModuleInfoOnSourcePath(Path base) throws Exception {
//note: avoiding use of java.base, as that gets special handling on some places:
Path src = base.resolve("src");
tb.writeJavaFiles(src,
@@ -147,7 +149,7 @@
}
@Test
- void testNoModuleInfoInClassOutput(Path base) throws Exception {
+ public void testNoModuleInfoInClassOutput(Path base) throws Exception {
//note: avoiding use of java.base, as that gets special handling on some places:
Path srcMod = base.resolve("src-mod");
tb.writeJavaFiles(srcMod,
@@ -187,7 +189,7 @@
}
@Test
- void testModuleSourcePathXModule(Path base) throws Exception {
+ public void testModuleSourcePathXModule(Path base) throws Exception {
//note: avoiding use of java.base, as that gets special handling on some places:
Path src = base.resolve("src");
tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
@@ -210,7 +212,7 @@
}
@Test
- void testXModuleTooMany(Path base) throws Exception {
+ public void testXModuleTooMany(Path base) throws Exception {
//note: avoiding use of java.base, as that gets special handling on some places:
Path src = base.resolve("src");
tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
@@ -234,9 +236,9 @@
}
@Test
- void testWithModulePath(Path base) throws Exception {
+ public void testWithModulePath(Path base) throws Exception {
Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.classes("package pkg1; public interface E { }")
.build(module);
@@ -251,7 +253,7 @@
.writeAll();
//checks module bounds still exist
- new ModuleBuilder("m2")
+ new ModuleBuilder(tb, "m2")
.classes("package pkg2; public interface D { }")
.build(module);
@@ -275,14 +277,14 @@
}
@Test
- void testWithUpgradeModulePath(Path base) throws Exception {
+ public void testWithUpgradeModulePath(Path base) throws Exception {
Path module = base.resolve("modules");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.classes("package pkg1; public interface E { }")
.build(module);
Path upgrade = base.resolve("upgrade");
- new ModuleBuilder("m1")
+ new ModuleBuilder(tb, "m1")
.classes("package pkg1; public interface D { }")
.build(upgrade);
--- a/langtools/test/tools/lib/toolbox/JavacTask.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/lib/toolbox/JavacTask.java Fri May 06 06:23:30 2016 -0700
@@ -103,6 +103,16 @@
}
/**
+ * Sets the classpath.
+ * @param classpath the classpath
+ * @return this task object
+ */
+ public JavacTask classpath(List<Path> classpath) {
+ this.classpath = classpath;
+ return this;
+ }
+
+ /**
* Sets the sourcepath.
* @param sourcepath the sourcepath
* @return this task object
@@ -126,6 +136,16 @@
}
/**
+ * Sets the sourcepath.
+ * @param sourcepath the sourcepath
+ * @return this task object
+ */
+ public JavacTask sourcepath(List<Path> sourcepath) {
+ this.sourcepath = sourcepath;
+ return this;
+ }
+
+ /**
* Sets the output directory.
* @param outdir the output directory
* @return this task object
@@ -188,6 +208,18 @@
}
/**
+ * Sets the files to be compiled or analyzed.
+ * @param files the files
+ * @return this task object
+ */
+ public JavacTask files(List<Path> files) {
+ this.files = files.stream()
+ .map(Path::toString)
+ .collect(Collectors.toList());
+ return this;
+ }
+
+ /**
* Sets the sources to be compiled or analyzed.
* Each source string is converted into an in-memory object that
* can be passed directly to the compiler.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * 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 toolbox;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ModuleBuilder {
+
+ private final ToolBox tb;
+ private final String name;
+ private String requires = "";
+ private String exports = "";
+ private String uses = "";
+ private String provides = "";
+ private String modulePath = "";
+ private List<String> content = new ArrayList<>();
+
+ public ModuleBuilder(ToolBox tb, String name) {
+ this.tb = tb;
+ this.name = name;
+ }
+
+ public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
+ return requires("public " + requires, modulePath);
+ }
+
+ public ModuleBuilder requires(String requires, Path... modulePath) {
+ this.requires += " requires " + requires + ";\n";
+ this.modulePath += Arrays.stream(modulePath)
+ .map(Path::toString)
+ .collect(Collectors.joining(File.pathSeparator));
+ return this;
+ }
+
+ public ModuleBuilder exportsTo(String pkg, String module) {
+ return exports(pkg + " to " + module);
+ }
+
+ public ModuleBuilder exports(String pkg) {
+ this.exports += " exports " + pkg + ";\n";
+ return this;
+ }
+
+ public ModuleBuilder uses(String uses) {
+ this.uses += " uses " + uses + ";\n";
+ return this;
+ }
+
+ public ModuleBuilder provides(String service, String implementation) {
+ this.provides += " provides " + service + " with " + implementation + ";\n";
+ return this;
+ }
+
+ public ModuleBuilder classes(String... content) {
+ this.content.addAll(Arrays.asList(content));
+ return this;
+ }
+
+ public Path write(Path where) throws IOException {
+ Files.createDirectories(where);
+ List<String> sources = new ArrayList<>();
+ sources.add("module " + name + "{"
+ + requires
+ + exports
+ + uses
+ + provides
+ + "}");
+ sources.addAll(content);
+ Path moduleSrc = where.resolve(name + "/src");
+ tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{}));
+ return moduleSrc;
+ }
+
+ public void build(Path where) throws IOException {
+ Path moduleSrc = write(where);
+ new JavacTask(tb)
+ .outdir(where.resolve(name))
+ .options("-mp", modulePath)
+ .files(tb.findJavaFiles(moduleSrc))
+ .run()
+ .writeAll();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/lib/toolbox/TestRunner.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,119 @@
+/*
+ * 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 toolbox;
+
+import java.io.PrintStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.function.Function;
+
+/**
+ * Utility class to manage and execute sub-tests within a test.
+ *
+ * This class does the following:
+ * <ul>
+ * <li> invokes those test methods annotated with @Test
+ * <li> keeps track of successful and failed tests
+ * <li> throws an Exception if any test fails.
+ * <li> provides a test summary at the end of the run.
+ * </ul>
+
+ * Tests must extend this class, annotate the test methods
+ * with @Test and call one of the runTests method.
+ */
+public abstract class TestRunner {
+ /** Marker annotation for test cases. */
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface Test { }
+
+ int testCount = 0;
+ int errorCount = 0;
+
+ public String testName = null;
+
+ protected PrintStream out;
+
+ /**
+ * Constructs the Object.
+ * @param out the PrintStream to print output to.
+ */
+ public TestRunner(PrintStream out) {
+ this.out = out;
+ }
+
+ /**
+ * Invoke all methods annotated with @Test.
+ * @throws java.lang.Exception if any errors occur
+ */
+ protected void runTests() throws Exception {
+ runTests(f -> new Object[0]);
+ }
+
+ /**
+ * Invoke all methods annotated with @Test.
+ * @param f a lambda expression to specify arguments for the test method
+ * @throws java.lang.Exception if any errors occur
+ */
+ protected void runTests(Function<Method, Object[]> f) throws Exception {
+ for (Method m : getClass().getDeclaredMethods()) {
+ Annotation a = m.getAnnotation(Test.class);
+ if (a != null) {
+ testName = m.getName();
+ try {
+ testCount++;
+ out.println("test: " + testName);
+ m.invoke(this, f.apply(m));
+ } catch (InvocationTargetException e) {
+ errorCount++;
+ Throwable cause = e.getCause();
+ out.println("Exception: " + e.getCause());
+ cause.printStackTrace(out);
+ }
+ out.println();
+ }
+ }
+
+ if (testCount == 0) {
+ throw new Error("no tests found");
+ }
+
+ StringBuilder summary = new StringBuilder();
+ if (testCount != 1) {
+ summary.append(testCount).append(" tests");
+ }
+ if (errorCount > 0) {
+ if (summary.length() > 0) {
+ summary.append(", ");
+ }
+ summary.append(errorCount).append(" errors");
+ }
+ out.println(summary);
+ if (errorCount > 0) {
+ throw new Exception(errorCount + " errors found");
+ }
+ }
+}
--- a/langtools/test/tools/lib/toolbox/ToolBox.java Fri May 06 11:47:45 2016 +0300
+++ b/langtools/test/tools/lib/toolbox/ToolBox.java Fri May 06 06:23:30 2016 -0700
@@ -41,6 +41,7 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -49,6 +50,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -315,7 +317,7 @@
* Reads the lines of a file.
* The file is read using the default character encoding.
* @param path the file to be read
- * @return the lines of the file.
+ * @return the lines of the file
* @throws IOException if an error occurred while reading the file
*/
public List<String> readAllLines(String path) throws IOException {
@@ -326,7 +328,7 @@
* Reads the lines of a file.
* The file is read using the default character encoding.
* @param path the file to be read
- * @return the lines of the file.
+ * @return the lines of the file
* @throws IOException if an error occurred while reading the file
*/
public List<String> readAllLines(Path path) throws IOException {
@@ -348,7 +350,7 @@
* Reads the lines of a file using the given encoding.
* @param path the file to be read
* @param encoding the encoding to be used to read the file
- * @return the lines of the file.
+ * @return the lines of the file
* @throws IOException if an error occurred while reading the file
*/
public List<String> readAllLines(Path path, String encoding) throws IOException {
@@ -360,6 +362,30 @@
}
/**
+ * Find .java files in one or more directories.
+ * <p>Similar to the shell "find" command: {@code find paths -name \*.java}.
+ * @param paths the directories in which to search for .java files
+ * @return the .java files found
+ * @throws IOException if an error occurred while searching for files
+ */
+ public Path[] findJavaFiles(Path... paths) throws IOException {
+ Set<Path> files = new TreeSet<>(); // use TreeSet to force a consistent order
+ for (Path p : paths) {
+ Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ if (file.getFileName().toString().endsWith(".java")) {
+ files.add(file);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ return files.toArray(new Path[files.size()]);
+ }
+
+ /**
* Writes a file containing the given content.
* Any necessary directories for the file will be created.
* @param path where to write the file
--- a/make/CompileJavaModules.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/CompileJavaModules.gmk Fri May 06 06:23:30 2016 -0700
@@ -99,7 +99,7 @@
################################################################################
java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \
- '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation
+ '-Xdoclint/package:java.*,javax.*'
java.desktop_COPY := .gif .png .wav .txt .xml .css .pf
java.desktop_CLEAN := iio-plugin.properties cursors.properties
--- a/make/CreateJmods.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/CreateJmods.gmk Fri May 06 06:23:30 2016 -0700
@@ -82,7 +82,7 @@
--os-version $(REQUIRED_OS_VERSION) \
--modulepath $(IMAGES_OUTPUTDIR)/jmods\
--hash-dependencies '.*' \
- --exclude '**_the.*' \
+ --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.pdb,*.map}' \
$(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
$(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@
--- a/make/GensrcModuleInfo.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/GensrcModuleInfo.gmk Fri May 06 06:23:30 2016 -0700
@@ -78,21 +78,30 @@
# let space represent new lines in the variable as $(shell) normalizes all
# whitespace.
$(foreach f, $(MOD_FILES), \
- $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v ".\*" $f | $(TR) ' ' '/')))
+ $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v -e ".\*" -e "//" $f | $(TR) ' ' '/')))
+
+ # Separate the modifications into qualified exports and the rest
+ MODS_QUALIFIED_EXPORTS := $(call containing, /to/, $(MOD_FILE_CONTENTS))
+ MODS_REST := $(filter-out $(MODS_QUALIFIED_EXPORTS), $(MOD_FILE_CONTENTS))
# Filter the contents for modules that are actually being built
MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES)))
- MODULES_FILTER += provides%
- MODIFICATIONS := $(filter $(MODULES_FILTER), $(MOD_FILE_CONTENTS))
+ MODIFICATIONS := $(filter $(MODULES_FILTER), $(MODS_QUALIFIED_EXPORTS)) \
+ $(MODS_REST)
# Convert the modification lines into arguments for the modification tool.
# Filter out modifications for non existing to-modules.
$(foreach line, $(MODIFICATIONS), \
$(eval split_line := $(subst /,$(SPACE),$(line))) \
$(eval command := $(word 1, $(split_line))) \
- $(eval package := $(word 2, $(split_line))) \
+ $(eval package := $(patsubst %;,%,$(word 2, $(split_line)))) \
$(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \
- $(eval ARGS += -$(command) $(package)/$(to_module)))
+ $(if $(to_module), \
+ $(eval ARGS += -$(command) $(package)/$(to_module)) \
+ , \
+ $(eval ARGS += -$(command) $(package)) \
+ ) \
+ )
ifneq ($(ARGS), )
$(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \
--- a/make/Images.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/Images.gmk Fri May 06 06:23:30 2016 -0700
@@ -423,6 +423,55 @@
endif
################################################################################
+# Debug symbols
+# Since debug symbols are not included in the jmod files, they need to be copied
+# in manually after generating the images.
+
+ALL_JDK_MODULES := $(JDK_MODULES)
+ALL_JRE_MODULES := $(sort $(JRE_MODULES), $(foreach m, $(JRE_MODULES), \
+ $(call FindTransitiveDepsForModule, $m)))
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+ LIBS_TARGET_SUBDIR := bin
+else
+ LIBS_TARGET_SUBDIR := lib
+endif
+
+DEBUGINFO_SUFFIXES := .diz .debuginfo .pdb .map
+
+# Param 1 - dir to find debuginfo files in
+FindDebuginfoFiles = \
+ $(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
+ $(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
+ $(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
+
+# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
+# dirs.
+ifeq ($(OPENJDK_TARGET_OS)-$(ZIP_EXTERNAL_DEBUG_SYMBOLS), macosx-false)
+ $(eval $(call FillCacheFind, \
+ $(SUPPORT_OUTPUTDIR)/modules_cmds $(SUPPORT_OUTPUTDIR)/modules_libs/))
+ FindDebuginfoFiles = \
+ $(if $(wildcard $1), $(call containing, .dSYM/, $(call CacheFind, $1)))
+endif
+
+# Param 1 - either JDK or JRE
+SetupCopyDebuginfo = \
+ $(foreach m, $(ALL_$1_MODULES), \
+ $(eval $(call SetupCopyFiles, COPY_$1_LIBS_DEBUGINFO_$m, \
+ SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/$m, \
+ DEST := $($1_IMAGE_DIR)/$(LIBS_TARGET_SUBDIR), \
+ FILES := $(call FindDebuginfoFiles, \
+ $(SUPPORT_OUTPUTDIR)/modules_libs/$m), \
+ )) \
+ $(eval $1_TARGETS += $$(COPY_$1_LIBS_DEBUGINFO_$m)) \
+ )
+
+# No space before argument to avoid having to put $(strip ) everywhere in
+# implementation above.
+$(call SetupCopyDebuginfo,JDK)
+$(call SetupCopyDebuginfo,JRE)
+
+################################################################################
# Include custom post hook here to make it possible to augment the target lists
# before actual target prerequisites are declared.
--- a/make/Init.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/Init.gmk Fri May 06 06:23:30 2016 -0700
@@ -268,8 +268,13 @@
##############################################################################
MAIN_TARGETS := $(SEQUENTIAL_TARGETS) $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE)
+ # If building the default target, add what they are to the description.
+ DESCRIPTION_TARGETS := $(strip $(MAIN_TARGETS))
+ ifeq ($(DESCRIPTION_TARGETS), default)
+ DESCRIPTION_TARGETS += ($(DEFAULT_MAKE_TARGET))
+ endif
TARGET_DESCRIPTION := target$(if $(word 2, $(MAIN_TARGETS)),s) \
- '$(strip $(MAIN_TARGETS))' in configuration '$(CONF_NAME)'
+ '$(strip $(DESCRIPTION_TARGETS))' in configuration '$(CONF_NAME)'
# MAKEOVERRIDES is automatically set and propagated by Make to sub-Make calls.
# We need to clear it of the init-specific variables. The user-specified
--- a/make/Javadoc.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/Javadoc.gmk Fri May 06 06:23:30 2016 -0700
@@ -1580,7 +1580,7 @@
JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages
# The modules required to be documented
-JDKNET_MODULES = java.base
+JDKNET_MODULES = jdk.net
jdknetdocs: $(JDKNET_INDEX_HTML)
--- a/make/Jprt.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/Jprt.gmk Fri May 06 06:23:30 2016 -0700
@@ -108,8 +108,8 @@
SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR)
# Bundle up the images
-JPRT_TARGET ?= all
-ifeq ($(JPRT_TARGET), all)
+JPRT_TARGET ?= default
+ifeq ($(JPRT_TARGET), default)
bundles: $(JPRT_TARGET)
@$(call TargetEnter)
$(MKDIR) -p $(BUILD_OUTPUT)/bundles
--- a/make/Main.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/Main.gmk Fri May 06 06:23:30 2016 -0700
@@ -340,10 +340,10 @@
docs-jvmtidoc:
+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk jvmtidocs)
-zip-docs: docs-javadoc docs-jvmtidoc
+zip-docs:
+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk zip-docs)
-ALL_TARGETS += docs-javadoc docs-jvmtidoc
+ALL_TARGETS += docs-javadoc docs-jvmtidoc zip-docs
################################################################################
# Cross compilation support
@@ -602,6 +602,8 @@
docs-jvmtidoc: hotspot
+ zip-docs: docs-javadoc docs-jvmtidoc
+
test: jimages test-image
create-buildjdk-copy: jdk.jlink-java java.base-gendata
@@ -703,7 +705,7 @@
endif
# This target builds the documentation image
-docs-image: zip-docs
+docs-image: docs-javadoc docs-jvmtidoc
# This target builds the test image
test-image: prepare-test-image test-image-hotspot-jtreg-native \
@@ -727,7 +729,7 @@
docs: docs-image
all: all-images
-ALL_TARGETS += default jdk images docs all zip-docs
+ALL_TARGETS += default jdk images docs all
################################################################################
################################################################################
@@ -829,6 +831,10 @@
################################################################################
+
+# workaround issue when building open targets when closed jib-profiles.js is used
+installer: product-images test-image
+
.PHONY: $(ALL_TARGETS)
FRC: # Force target
--- a/make/common/Modules.gmk Fri May 06 11:47:45 2016 +0300
+++ b/make/common/Modules.gmk Fri May 06 06:23:30 2016 -0700
@@ -63,6 +63,7 @@
java.xml.crypto \
jdk.httpserver \
jdk.management \
+ jdk.net \
jdk.sctp \
jdk.security.auth \
jdk.security.jgss \
@@ -185,7 +186,8 @@
$(call GetModuleNameFromModuleInfo, $(MODULE_INFOS))))
FindImportedModules = \
- $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*)))
+ $(filter-out $(MODULES_FILTER), \
+ $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*))))
# Find all source dirs for a particular module
# $1 - Module to find source dirs for
--- a/nashorn/.hgtags Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/.hgtags Fri May 06 06:23:30 2016 -0700
@@ -349,3 +349,4 @@
a5d1990fd32d908da8154d79116fce8013ba4d40 jdk-9+113
ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114
295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115
+208388a5622dcca8227d6ad6c268f2c88087d283 jdk-9+116
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri May 06 06:23:30 2016 -0700
@@ -4310,7 +4310,7 @@
* @param ident identifier for block or function where applicable
*/
private void printSymbols(final Block block, final FunctionNode function, final String ident) {
- if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
+ if (compiler.getScriptEnvironment()._print_symbols || function.getDebugFlag(FunctionNode.DEBUG_PRINT_SYMBOLS)) {
final PrintWriter out = compiler.getScriptEnvironment().getErr();
out.println("[BLOCK in '" + ident + "']");
if (!block.printSymbols(out)) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java Fri May 06 06:23:30 2016 -0700
@@ -278,12 +278,12 @@
final PrintWriter err = senv.getErr();
//TODO separate phase for the debug printouts for abstraction and clarity
- if (senv._print_lower_ast || fn.getFlag(FunctionNode.IS_PRINT_LOWER_AST)) {
+ if (senv._print_lower_ast || fn.getDebugFlag(FunctionNode.DEBUG_PRINT_LOWER_AST)) {
err.println("Lower AST for: " + quote(newFunctionNode.getName()));
err.println(new ASTWriter(newFunctionNode));
}
- if (senv._print_lower_parse || fn.getFlag(FunctionNode.IS_PRINT_LOWER_PARSE)) {
+ if (senv._print_lower_parse || fn.getDebugFlag(FunctionNode.DEBUG_PRINT_LOWER_PARSE)) {
err.println("Lower AST for: " + quote(newFunctionNode.getName()));
err.println(new PrintVisitor(newFunctionNode));
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Fri May 06 06:23:30 2016 -0700
@@ -175,7 +175,9 @@
// we still use IS_SPLIT as the criteria in CompilationPhase.SERIALIZE_SPLIT_PHASE.
FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT,
body,
- null
+ null,
+ originalFn.getModule(),
+ originalFn.getDebugFlags()
)
.setCompileUnit(lc, splitNode.getCompileUnit());
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Fri May 06 06:23:30 2016 -0700
@@ -435,7 +435,7 @@
}
@Override
- public Node leaveBIND(final BinaryNode binaryNode) {
+ public Node leaveARROW(final BinaryNode binaryNode) {
return binaryNodeWeight(binaryNode);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java Fri May 06 06:23:30 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -48,12 +48,13 @@
* @param property property
*/
public AccessNode(final long token, final int finish, final Expression base, final String property) {
- super(token, finish, base, false);
+ super(token, finish, base, false, false);
this.property = property;
}
- private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id) {
- super(accessNode, base, isFunction, type, id);
+ private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction,
+ final Type type, final int id, final boolean isSuper) {
+ super(accessNode, base, isFunction, type, id, isSuper);
this.property = property;
}
@@ -105,7 +106,7 @@
if (this.base == base) {
return this;
}
- return new AccessNode(this, base, property, isFunction(), type, programPoint);
+ return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
}
@Override
@@ -113,7 +114,7 @@
if (this.type == type) {
return this;
}
- return new AccessNode(this, base, property, isFunction(), type, programPoint);
+ return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
}
@Override
@@ -121,7 +122,7 @@
if (this.programPoint == programPoint) {
return this;
}
- return new AccessNode(this, base, property, isFunction(), type, programPoint);
+ return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
}
@Override
@@ -129,6 +130,14 @@
if (isFunction()) {
return this;
}
- return new AccessNode(this, base, property, true, type, programPoint);
+ return new AccessNode(this, base, property, true, type, programPoint, isSuper());
+ }
+
+ @Override
+ public AccessNode setIsSuper() {
+ if (isSuper()) {
+ return this;
+ }
+ return new AccessNode(this, base, property, isFunction(), type, programPoint, true);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java Fri May 06 06:23:30 2016 -0700
@@ -52,6 +52,9 @@
/** Program point id */
protected final int programPoint;
+ /** Super property access. */
+ private final boolean isSuper;
+
/**
* Constructor
*
@@ -59,13 +62,15 @@
* @param finish finish
* @param base base node
* @param isFunction is this a function
+ * @param isSuper is this a super property access
*/
- public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) {
+ public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean isSuper) {
super(token, base.getStart(), finish);
this.base = base;
this.isFunction = isFunction;
this.type = null;
this.programPoint = INVALID_PROGRAM_POINT;
+ this.isSuper = isSuper;
}
/**
@@ -75,13 +80,15 @@
* @param isFunction is this a function
* @param callSiteType the callsite type for this base node, either optimistic or conservative
* @param programPoint program point id
+ * @param isSuper is this a super property access
*/
- protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint) {
+ protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint, final boolean isSuper) {
super(baseNode);
this.base = base;
this.isFunction = isFunction;
this.type = callSiteType;
this.programPoint = programPoint;
+ this.isSuper = isSuper;
}
/**
@@ -136,4 +143,17 @@
*/
public abstract BaseNode setIsFunction();
+ /**
+ * @return {@code true} if a SuperProperty access.
+ */
+ public boolean isSuper() {
+ return isSuper;
+ }
+
+ /**
+ * Mark this node as being a SuperProperty access.
+ *
+ * @return a base node identical to this one in all aspects except with its super flag set.
+ */
+ public abstract BaseNode setIsSuper();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Fri May 06 06:23:30 2016 -0700
@@ -65,24 +65,39 @@
private final LocalVariableConversion conversion;
/** Flag indicating that this block needs scope */
- public static final int NEEDS_SCOPE = 1 << 0;
+ public static final int NEEDS_SCOPE = 1 << 0;
/**
* Is this block tagged as terminal based on its contents
* (usually the last statement)
*/
- public static final int IS_TERMINAL = 1 << 2;
+ public static final int IS_TERMINAL = 1 << 2;
/**
* Is this block the eager global scope - i.e. the original program. This isn't true for the
* outermost level of recompiles
*/
- public static final int IS_GLOBAL_SCOPE = 1 << 3;
+ public static final int IS_GLOBAL_SCOPE = 1 << 3;
/**
* Is this block a synthetic one introduced by Parser?
*/
- public static final int IS_SYNTHETIC = 1 << 4;
+ public static final int IS_SYNTHETIC = 1 << 4;
+
+ /**
+ * Is this the function body block? May not be the first, if parameter list contains expressions.
+ */
+ public static final int IS_BODY = 1 << 5;
+
+ /**
+ * Is this the parameter initialization block? If present, must be the first block, immediately wrapping the function body block.
+ */
+ public static final int IS_PARAMETER_BLOCK = 1 << 6;
+
+ /**
+ * Marks the variable declaration block for case clauses of a switch statement.
+ */
+ public static final int IS_SWITCH_BLOCK = 1 << 7;
/**
* Constructor
@@ -489,4 +504,31 @@
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
return Acceptor.accept(this, visitor);
}
+
+ /**
+ * Checks if this is a function body.
+ *
+ * @return true if the function body flag is set
+ */
+ public boolean isFunctionBody() {
+ return getFlag(IS_BODY);
+ }
+
+ /**
+ * Checks if this is a parameter block.
+ *
+ * @return true if the parameter block flag is set
+ */
+ public boolean isParameterBlock() {
+ return getFlag(IS_PARAMETER_BLOCK);
+ }
+
+ /**
+ * Checks whether this is a switch block.
+ *
+ * @return true if this is a switch block
+ */
+ public boolean isSwitchBlock() {
+ return getFlag(IS_SWITCH_BLOCK);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * 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.nashorn.internal.ir;
+
+import java.util.Collections;
+import java.util.List;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR representation for class definitions.
+ */
+public class ClassNode extends Expression {
+ private static final long serialVersionUID = 1L;
+
+ private final IdentNode ident;
+ private final Expression classHeritage;
+ private final PropertyNode constructor;
+ private final List<PropertyNode> classElements;
+ private final int line;
+
+ /**
+ * Constructor.
+ *
+ * @param line line number
+ * @param token token
+ * @param finish finish
+ * @param ident ident
+ * @param classHeritage class heritage
+ * @param constructor constructor
+ * @param classElements class elements
+ */
+ public ClassNode(final int line, final long token, final int finish, final IdentNode ident, final Expression classHeritage, final PropertyNode constructor,
+ final List<PropertyNode> classElements) {
+ super(token, finish);
+ this.line = line;
+ this.ident = ident;
+ this.classHeritage = classHeritage;
+ this.constructor = constructor;
+ this.classElements = classElements;
+ }
+
+ /**
+ * Class identifier. Optional.
+ *
+ * @return the class identifier
+ */
+ public IdentNode getIdent() {
+ return ident;
+ }
+
+ /**
+ * The expression of the {@code extends} clause. Optional.
+ *
+ * @return the class heritage
+ */
+ public Expression getClassHeritage() {
+ return classHeritage;
+ }
+
+ /**
+ * Get the constructor method definition.
+ *
+ * @return the constructor
+ */
+ public PropertyNode getConstructor() {
+ return constructor;
+ }
+
+ /**
+ * Get method definitions except the constructor.
+ *
+ * @return the class elements
+ */
+ public List<PropertyNode> getClassElements() {
+ return Collections.unmodifiableList(classElements);
+ }
+
+ /**
+ * Returns the line number.
+ *
+ * @return the line number
+ */
+ public int getLineNumber() {
+ return line;
+ }
+
+ @Override
+ public Type getType() {
+ return Type.OBJECT;
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ if (visitor.enterClassNode(this)) {
+ return visitor.leaveClassNode(this);
+ }
+
+ return this;
+ }
+
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
+ sb.append("class");
+ if (ident != null) {
+ sb.append(' ');
+ ident.toString(sb, printType);
+ }
+ if (classHeritage != null) {
+ sb.append(" extends");
+ classHeritage.toString(sb, printType);
+ }
+ sb.append(" {");
+ if (constructor != null) {
+ constructor.toString(sb, printType);
+ }
+ for (final PropertyNode classElement : classElements) {
+ sb.append(" ");
+ classElement.toString(sb, printType);
+ }
+ sb.append("}");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionList.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * 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.nashorn.internal.ir;
+
+import java.util.Collections;
+import java.util.List;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR for CoverParenthesizedExpressionAndArrowParameterList, used only during parsing.
+ */
+public final class ExpressionList extends Expression {
+ private static final long serialVersionUID = 1L;
+
+ private final List<Expression> expressions;
+
+ /**
+ * Constructor.
+ *
+ * @param token token
+ * @param finish finish
+ * @param expressions expression
+ */
+ public ExpressionList(final long token, final int finish, final List<Expression> expressions) {
+ super(token, finish);
+ this.expressions = expressions;
+ }
+
+ /**
+ * Get the list of expressions.
+ *
+ * @return the list of expressions
+ */
+ public List<Expression> getExpressions() {
+ return Collections.unmodifiableList(expressions);
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Type getType() {
+ return null;
+ }
+
+ @Override
+ public void toString(StringBuilder sb, boolean printType) {
+ sb.append("(");
+ boolean first = true;
+ for (Expression expression : expressions) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ expression.toString(sb, printType);
+ }
+ sb.append(")");
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Fri May 06 06:23:30 2016 -0700
@@ -90,7 +90,6 @@
this.init = init;
this.modify = modify;
this.iterator = null;
-
}
private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Fri May 06 06:23:30 2016 -0700
@@ -69,7 +69,13 @@
/** a getter, @see {@link UserAccessorProperty} */
GETTER,
/** a setter, @see {@link UserAccessorProperty} */
- SETTER
+ SETTER,
+ /** an arrow function */
+ ARROW,
+ /** a generator function */
+ GENERATOR,
+ /** a module function */
+ MODULE
}
/** Source of entity. */
@@ -122,6 +128,12 @@
/** Root class for function */
private final Class<?> rootClass;
+ /** The ES6 module */
+ private final Module module;
+
+ /** The debug flags */
+ private final int debugFlags;
+
/** Is anonymous function flag. */
public static final int IS_ANONYMOUS = 1 << 0;
@@ -172,49 +184,21 @@
/**
* Is this function the top-level program?
*/
- public static final int IS_PROGRAM = 1 << 13;
+ public static final int IS_PROGRAM = 1 << 13;
/**
* Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
* can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
* use the symbol in their parent scope instead when they reference themselves by name.
*/
- public static final int USES_SELF_SYMBOL = 1 << 14;
+ public static final int USES_SELF_SYMBOL = 1 << 14;
/** Does this function use the "this" keyword? */
- public static final int USES_THIS = 1 << 15;
+ public static final int USES_THIS = 1 << 15;
/** Is this declared in a dynamic context */
- public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
-
- /**
- * The following flags are derived from directive comments within this function.
- * Note that even IS_STRICT is one such flag but that requires special handling.
- */
+ public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
- /** parser, print parse tree */
- public static final int IS_PRINT_PARSE = 1 << 17;
- /** parser, print lower parse tree */
- public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
- /** parser, print AST */
- public static final int IS_PRINT_AST = 1 << 19;
- /** parser, print lower AST */
- public static final int IS_PRINT_LOWER_AST = 1 << 20;
- /** parser, print symbols */
- public static final int IS_PRINT_SYMBOLS = 1 << 21;
-
- // callsite tracing, profiling within this function
- /** profile callsites in this function? */
- public static final int IS_PROFILE = 1 << 22;
-
- /** trace callsite enterexit in this function? */
- public static final int IS_TRACE_ENTEREXIT = 1 << 23;
-
- /** trace callsite misses in this function? */
- public static final int IS_TRACE_MISSES = 1 << 24;
-
- /** trace callsite values in this function? */
- public static final int IS_TRACE_VALUES = 1 << 25;
/**
* Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
@@ -222,18 +206,41 @@
* Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
* will, however, cache the value of this flag.
*/
- public static final int NEEDS_CALLEE = 1 << 26;
+ public static final int NEEDS_CALLEE = 1 << 17;
/**
* Is the function node cached?
*/
- public static final int IS_CACHED = 1 << 27;
+ public static final int IS_CACHED = 1 << 18;
+
+ /**
+ * Does this function contain a super call? (cf. ES6 14.3.5 Static Semantics: HasDirectSuper)
+ */
+ public static final int ES6_HAS_DIRECT_SUPER = 1 << 19;
+
+ /**
+ * Does this function use the super binding?
+ */
+ public static final int ES6_USES_SUPER = 1 << 20;
- /** extension callsite flags mask */
- public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
- IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
- IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
- IS_TRACE_MISSES | IS_TRACE_VALUES;
+ /**
+ * Is this function a (class or object) method?
+ */
+ public static final int ES6_IS_METHOD = 1 << 21;
+
+ /**
+ * Is this the constructor method?
+ */
+ public static final int ES6_IS_CLASS_CONSTRUCTOR = 1 << 22;
+
+ /** Is this the constructor of a subclass (i.e., a class with an extends declaration)? */
+ public static final int ES6_IS_SUBCLASS_CONSTRUCTOR = 1 << 23;
+
+ /** is this a strong mode function? */
+ public static final int ES6_IS_STRONG = 1 << 24;
+
+ /** Does this function use new.target? */
+ public static final int ES6_USES_NEW_TARGET = 1 << 25;
/** Does this function or any nested functions contain an eval? */
private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
@@ -247,8 +254,44 @@
/** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
+
+ /**
+ * The following flags are derived from directive comments within this function.
+ * Note that even IS_STRICT is one such flag but that requires special handling.
+ */
+
+ /** parser, print parse tree */
+ public static final int DEBUG_PRINT_PARSE = 1 << 0;
+ /** parser, print lower parse tree */
+ public static final int DEBUG_PRINT_LOWER_PARSE = 1 << 1;
+ /** parser, print AST */
+ public static final int DEBUG_PRINT_AST = 1 << 2;
+ /** parser, print lower AST */
+ public static final int DEBUG_PRINT_LOWER_AST = 1 << 3;
+ /** parser, print symbols */
+ public static final int DEBUG_PRINT_SYMBOLS = 1 << 4;
+
+ // callsite tracing, profiling within this function
+ /** profile callsites in this function? */
+ public static final int DEBUG_PROFILE = 1 << 5;
+
+ /** trace callsite enterexit in this function? */
+ public static final int DEBUG_TRACE_ENTEREXIT = 1 << 6;
+
+ /** trace callsite misses in this function? */
+ public static final int DEBUG_TRACE_MISSES = 1 << 7;
+
+ /** trace callsite values in this function? */
+ public static final int DEBUG_TRACE_VALUES = 1 << 8;
+
+ /** extension callsite flags mask */
+ public static final int DEBUG_CALLSITE_FLAGS = DEBUG_PRINT_PARSE |
+ DEBUG_PRINT_LOWER_PARSE | DEBUG_PRINT_AST | DEBUG_PRINT_LOWER_AST |
+ DEBUG_PRINT_SYMBOLS | DEBUG_PROFILE | DEBUG_TRACE_ENTEREXIT |
+ DEBUG_TRACE_MISSES | DEBUG_TRACE_VALUES;
+
/** What is the return type of this function? */
- private Type returnType = Type.UNKNOWN;
+ public Type returnType = Type.UNKNOWN;
/**
* Constructor
@@ -267,6 +310,8 @@
* @param flags initial flags
* @param body body of the function
* @param endParserState The parser state at the end of the parsing.
+ * @param module the module
+ * @param debugFlags the debug flags
*/
public FunctionNode(
final Source source,
@@ -282,7 +327,9 @@
final FunctionNode.Kind kind,
final int flags,
final Block body,
- final Object endParserState) {
+ final Object endParserState,
+ final Module module,
+ final int debugFlags) {
super(token, finish);
this.source = source;
@@ -299,7 +346,9 @@
this.body = body;
this.thisProperties = 0;
this.rootClass = null;
- this.endParserState = endParserState;
+ this.endParserState = endParserState;
+ this.module = module;
+ this.debugFlags = debugFlags;
}
private FunctionNode(
@@ -335,6 +384,8 @@
this.ident = functionNode.ident;
this.kind = functionNode.kind;
this.firstToken = functionNode.firstToken;
+ this.module = functionNode.module;
+ this.debugFlags = functionNode.debugFlags;
}
@Override
@@ -366,23 +417,23 @@
}
// quick check for extension callsite flags turned on by directives.
- if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
+ if ((debugFlags & DEBUG_CALLSITE_FLAGS) == 0) {
return callsiteFlags;
}
- if (getFlag(IS_PROFILE)) {
+ if (getDebugFlag(DEBUG_PROFILE)) {
callsiteFlags |= CALLSITE_PROFILE;
}
- if (getFlag(IS_TRACE_MISSES)) {
+ if (getDebugFlag(DEBUG_TRACE_MISSES)) {
callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
}
- if (getFlag(IS_TRACE_VALUES)) {
+ if (getDebugFlag(DEBUG_TRACE_VALUES)) {
callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
}
- if (getFlag(IS_TRACE_ENTEREXIT)) {
+ if (getDebugFlag(DEBUG_TRACE_ENTEREXIT)) {
callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
}
@@ -466,23 +517,23 @@
public static int getDirectiveFlag(final String directive) {
switch (directive) {
case "nashorn callsite trace enterexit":
- return IS_TRACE_ENTEREXIT;
+ return DEBUG_TRACE_ENTEREXIT;
case "nashorn callsite trace misses":
- return IS_TRACE_MISSES;
+ return DEBUG_TRACE_MISSES;
case "nashorn callsite trace objects":
- return IS_TRACE_VALUES;
+ return DEBUG_TRACE_VALUES;
case "nashorn callsite profile":
- return IS_PROFILE;
+ return DEBUG_PROFILE;
case "nashorn print parse":
- return IS_PRINT_PARSE;
+ return DEBUG_PRINT_PARSE;
case "nashorn print lower parse":
- return IS_PRINT_LOWER_PARSE;
+ return DEBUG_PRINT_LOWER_PARSE;
case "nashorn print ast":
- return IS_PRINT_AST;
+ return DEBUG_PRINT_AST;
case "nashorn print lower ast":
- return IS_PRINT_LOWER_AST;
+ return DEBUG_PRINT_LOWER_AST;
case "nashorn print symbols":
- return IS_PRINT_SYMBOLS;
+ return DEBUG_PRINT_SYMBOLS;
default:
// unknown/unsupported directive
return 0;
@@ -579,6 +630,25 @@
}
/**
+ * Returns the debug flags for this function.
+ *
+ * @return the debug flags
+ */
+ public int getDebugFlags() {
+ return debugFlags;
+ }
+
+ /**
+ * Checks whether a debug flag is set for this function.
+ *
+ * @param debugFlag the debug flag
+ * @return true if the flag is set
+ */
+ public boolean getDebugFlag(final int debugFlag) {
+ return (debugFlags & debugFlag) != 0;
+ }
+
+ /**
* Returns true if the function is the top-level program.
* @return True if this function node represents the top-level program.
*/
@@ -1065,6 +1135,86 @@
return setFlag(lc, IS_CACHED);
}
+ /**
+ * Checks if the function is generated in strong mode.
+ *
+ * @return true if strong mode enabled for function
+ */
+ public boolean isStrong() {
+ return getFlag(ES6_IS_STRONG);
+ }
+
+ /**
+ * Checks if this is an ES6 method.
+ *
+ * @return true if the ES6 method flag is set
+ */
+ public boolean isMethod() {
+ return getFlag(ES6_IS_METHOD);
+ }
+
+ /**
+ * Checks if this function uses the ES6 super binding.
+ *
+ * @return true if the ES6 super flag is set
+ */
+ public boolean usesSuper() {
+ return getFlag(ES6_USES_SUPER);
+ }
+
+ /**
+ * Checks if this function directly uses the super binding.
+ *
+ * @return true if the ES6 has-direct-super flag is set
+ */
+ public boolean hasDirectSuper() {
+ return getFlag(ES6_HAS_DIRECT_SUPER);
+ }
+
+ /**
+ * Checks if this is an ES6 class constructor.
+ *
+ * @return true if the ES6 class constructor flag is set
+ */
+ public boolean isClassConstructor() {
+ return getFlag(ES6_IS_CLASS_CONSTRUCTOR);
+ }
+
+ /**
+ * Checks if this is an ES6 subclass constructor.
+ *
+ * @return true if the ES6 subclass constructor flag is set
+ */
+ public boolean isSubclassConstructor() {
+ return getFlag(ES6_IS_SUBCLASS_CONSTRUCTOR);
+ }
+
+ /**
+ * Checks if this function uses the ES6 new-targert.
+ *
+ * @return true if the ES6 new-target flag is set
+ */
+ public boolean usesNewTarget() {
+ return getFlag(ES6_USES_NEW_TARGET);
+ }
+
+ /**
+ * Checks if this is an ES6 module.
+ *
+ * @return true if this is an ES6 module
+ */
+ public boolean isModule() {
+ return kind == Kind.MODULE;
+ }
+
+ /**
+ * Returns the functions's ES6 module.
+ *
+ * @return the module, or null if this function is not part of one
+ */
+ public Module getModule() {
+ return module;
+ }
/**
* Get the compile unit used to compile this function
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java Fri May 06 06:23:30 2016 -0700
@@ -49,6 +49,11 @@
private static final int FUTURESTRICT_NAME = 1 << 3;
private static final int IS_DECLARED_HERE = 1 << 4;
private static final int IS_DEAD = 1 << 5;
+ private static final int DIRECT_SUPER = 1 << 6;
+ private static final int REST_PARAMETER = 1 << 7;
+ private static final int PROTO_PROPERTY = 1 << 8;
+ private static final int DEFAULT_PARAMETER = 1 << 9;
+ private static final int DESTRUCTURED_PARAMETER = 1 << 10;
/** Identifier. */
private final String name;
@@ -382,4 +387,94 @@
public LocalVariableConversion getLocalVariableConversion() {
return conversion;
}
+
+ /**
+ * Checks if this is a direct super identifier
+ *
+ * @return true if the direct super flag is set
+ */
+ public boolean isDirectSuper() {
+ return (flags & DIRECT_SUPER) != 0;
+ }
+
+ /**
+ * Return a new identifier with the direct super flag set.
+ *
+ * @return the new identifier
+ */
+ public IdentNode setIsDirectSuper() {
+ return new IdentNode(this, name, type, flags | DIRECT_SUPER, programPoint, conversion);
+ }
+
+ /**
+ * Checks if this is a rest parameter
+ *
+ * @return true if the rest parameter flag is set
+ */
+ public boolean isRestParameter() {
+ return (flags & REST_PARAMETER) != 0;
+ }
+
+ /**
+ * Return a new identifier with the rest parameter flag set.
+ *
+ * @return the new identifier
+ */
+ public IdentNode setIsRestParameter() {
+ return new IdentNode(this, name, type, flags | REST_PARAMETER, programPoint, conversion);
+ }
+
+ /**
+ * Checks if this is a proto property name.
+ *
+ * @return true if this is the proto property name
+ */
+ public boolean isProtoPropertyName() {
+ return (flags & PROTO_PROPERTY) != 0;
+ }
+
+ /**
+ * Return a new identifier with the proto property name flag set.
+ *
+ * @return the new identifier
+ */
+ public IdentNode setIsProtoPropertyName() {
+ return new IdentNode(this, name, type, flags | PROTO_PROPERTY, programPoint, conversion);
+ }
+
+ /**
+ * Checks whether this is a default parameter.
+ *
+ * @return true if this is a default parameter
+ */
+ public boolean isDefaultParameter() {
+ return (flags & DEFAULT_PARAMETER) != 0;
+ }
+
+ /**
+ * Return a new identifier with the default parameter flag set.
+ *
+ * @return the new identifier
+ */
+ public IdentNode setIsDefaultParameter() {
+ return new IdentNode(this, name, type, flags | DEFAULT_PARAMETER, programPoint, conversion);
+ }
+
+ /**
+ * Checks whether this is a destructured parameter.
+ *
+ * @return true if this is a destructured parameter
+ */
+ public boolean isDestructuredParameter() {
+ return (flags & DESTRUCTURED_PARAMETER) != 0;
+ }
+
+ /**
+ * Return a new identifier with the destructured parameter flag set.
+ *
+ * @return the new identifier
+ */
+ public IdentNode setIsDestructuredParameter() {
+ return new IdentNode(this, name, type, flags | DESTRUCTURED_PARAMETER, programPoint, conversion);
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java Fri May 06 06:23:30 2016 -0700
@@ -47,12 +47,13 @@
* @param index index for access
*/
public IndexNode(final long token, final int finish, final Expression base, final Expression index) {
- super(token, finish, base, false);
+ super(token, finish, base, false, false);
this.index = index;
}
- private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final Type type, final int programPoint) {
- super(indexNode, base, isFunction, type, programPoint);
+ private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction,
+ final Type type, final int programPoint, final boolean isSuper) {
+ super(indexNode, base, isFunction, type, programPoint, isSuper);
this.index = index;
}
@@ -101,7 +102,7 @@
if (this.base == base) {
return this;
}
- return new IndexNode(this, base, index, isFunction(), type, programPoint);
+ return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
/**
@@ -113,7 +114,7 @@
if(this.index == index) {
return this;
}
- return new IndexNode(this, base, index, isFunction(), type, programPoint);
+ return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
@Override
@@ -121,7 +122,7 @@
if (this.type == type) {
return this;
}
- return new IndexNode(this, base, index, isFunction(), type, programPoint);
+ return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
@Override
@@ -129,7 +130,7 @@
if (isFunction()) {
return this;
}
- return new IndexNode(this, base, index, true, type, programPoint);
+ return new IndexNode(this, base, index, true, type, programPoint, isSuper());
}
@Override
@@ -137,6 +138,14 @@
if (this.programPoint == programPoint) {
return this;
}
- return new IndexNode(this, base, index, isFunction(), type, programPoint);
+ return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
+ }
+
+ @Override
+ public IndexNode setIsSuper() {
+ if (isSuper()) {
+ return this;
+ }
+ return new IndexNode(this, base, index, isFunction(), type, programPoint, true);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,338 @@
+/*
+ * 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
+ * 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.nashorn.internal.ir;
+
+import java.util.List;
+
+/**
+ * ES6 Module information.
+ */
+public final class Module {
+
+ /** The synthetic binding name assigned to export default declarations with unnamed expressions. */
+ public static final String DEFAULT_EXPORT_BINDING_NAME = "*default*";
+
+ /** The {@code export default} name. */
+ public static final String DEFAULT_NAME = "default";
+
+ /** The {@code export *} name. */
+ public static final String STAR_NAME = "*";
+
+ /**
+ * A module ExportEntry record.
+ *
+ * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
+ */
+ public static final class ExportEntry {
+ private final String exportName;
+ private final String moduleRequest;
+ private final String importName;
+ private final String localName;
+
+ private ExportEntry(final String exportName, final String moduleRequest, final String importName, final String localName) {
+ this.exportName = exportName;
+ this.moduleRequest = moduleRequest;
+ this.importName = importName;
+ this.localName = localName;
+ }
+
+ /**
+ * Creates a {@code export *} export entry.
+ *
+ * @param moduleRequest the module request
+ * @return the export entry
+ */
+ public static ExportEntry exportStarFrom(final String moduleRequest) {
+ return new ExportEntry(null, moduleRequest, STAR_NAME, null);
+ }
+
+ /**
+ * Creates a {@code export default} export entry.
+ *
+ * @return the export entry
+ */
+ public static ExportEntry exportDefault() {
+ return exportDefault(DEFAULT_EXPORT_BINDING_NAME);
+ }
+
+ /**
+ * Creates a {@code export default} export entry with a local name.
+ *
+ * @param localName the local name
+ * @return the export entry
+ */
+ public static ExportEntry exportDefault(final String localName) {
+ return new ExportEntry(DEFAULT_NAME, null, null, localName);
+ }
+
+ /**
+ * Creates a export entry with a local name and export name.
+ *
+ * @param exportName the export name
+ * @param localName the local name
+ * @return the export entry
+ */
+ public static ExportEntry exportSpecifier(final String exportName, final String localName) {
+ return new ExportEntry(exportName, null, null, localName);
+ }
+
+ /**
+ * Creates a export entry with an export name.
+ *
+ * @param exportName the export name
+ * @return the export entry
+ */
+ public static ExportEntry exportSpecifier(final String exportName) {
+ return exportSpecifier(exportName, exportName);
+ }
+
+ /**
+ * Create a copy of this entry with the specified {@code module request} string.
+ *
+ * @param moduleRequest the module request
+ * @return the new export entry
+ */
+ public ExportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
+ return new ExportEntry(exportName, moduleRequest, localName, null);
+ }
+
+ /**
+ * Returns the entry's export name.
+ *
+ * @return the export name
+ */
+ public String getExportName() {
+ return exportName;
+ }
+
+ /**
+ * Returns the entry's module request.
+ *
+ * @return the module request
+ */
+ public String getModuleRequest() {
+ return moduleRequest;
+ }
+
+ /**
+ * Returns the entry's import name.
+ *
+ * @return the import name
+ */
+ public String getImportName() {
+ return importName;
+ }
+
+ /**
+ * Returns the entry's local name.
+ *
+ * @return the local name
+ */
+ public String getLocalName() {
+ return localName;
+ }
+
+ @Override
+ public String toString() {
+ return "ExportEntry [exportName=" + exportName + ", moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
+ }
+ }
+
+ /**
+ * An ImportEntry record.
+ *
+ * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
+ */
+ public static final class ImportEntry {
+ private final String moduleRequest;
+ private final String importName;
+ private final String localName;
+
+ private ImportEntry(final String moduleRequest, final String importName, final String localName) {
+ this.moduleRequest = moduleRequest;
+ this.importName = importName;
+ this.localName = localName;
+ }
+
+ /**
+ * Creates an import entry with default name.
+ *
+ * @param localName the local name
+ * @return the import entry
+ */
+ public static ImportEntry importDefault(final String localName) {
+ return new ImportEntry(null, DEFAULT_NAME, localName);
+ }
+
+ /**
+ * Creates an import entry with {@code *} import name.
+ *
+ * @param localName the local name
+ * @return the import entry
+ */
+ public static ImportEntry importStarAsNameSpaceFrom(final String localName) {
+ return new ImportEntry(null, STAR_NAME, localName);
+ }
+
+ /**
+ * Creates an import entry with the given import and local names.
+ *
+ * @param importName the import name
+ * @param localName the local name
+ * @return the import entry
+ */
+ public static ImportEntry importSpecifier(final String importName, final String localName) {
+ return new ImportEntry(null, importName, localName);
+ }
+
+ /**
+ * Creates a new import entry with the given import name.
+ *
+ * @param importName the import name
+ * @return the import entry
+ */
+ public static ImportEntry importSpecifier(final String importName) {
+ return importSpecifier(importName, importName);
+ }
+
+ /**
+ * Returns a copy of this import entry with the given module request.
+ *
+ * @param moduleRequest the module request
+ * @return the new import entry
+ */
+ public ImportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
+ return new ImportEntry(moduleRequest, importName, localName);
+ }
+
+ /**
+ * Returns the entry's module request.
+ *
+ * @return the module request
+ */
+ public String getModuleRequest() {
+ return moduleRequest;
+ }
+
+ /**
+ * Returns the entry's import name.
+ *
+ * @return the import name
+ */
+ public String getImportName() {
+ return importName;
+ }
+
+ /**
+ * Returns the entry's local name.
+ *
+ * @return the local name
+ */
+ public String getLocalName() {
+ return localName;
+ }
+
+ @Override
+ public String toString() {
+ return "ImportEntry [moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
+ }
+ }
+
+ private final List<String> requestedModules;
+ private final List<ImportEntry> importEntries;
+ private final List<ExportEntry> localExportEntries;
+ private final List<ExportEntry> indirectExportEntries;
+ private final List<ExportEntry> starExportEntries;
+
+ /**
+ * Creates a module with the specified requested modules and import and export entries.
+ *
+ * @param requestedModules the requested modules
+ * @param importEntries the import entries
+ * @param localExportEntries local export entries
+ * @param indirectExportEntries indirect export entries
+ * @param starExportEntries star export entries
+ */
+ public Module(final List<String> requestedModules, final List<ImportEntry> importEntries, final List<ExportEntry> localExportEntries,
+ final List<ExportEntry> indirectExportEntries, final List<ExportEntry> starExportEntries) {
+ this.requestedModules = requestedModules;
+ this.importEntries = importEntries;
+ this.localExportEntries = localExportEntries;
+ this.indirectExportEntries = indirectExportEntries;
+ this.starExportEntries = starExportEntries;
+ }
+
+ /**
+ * Returns the list of requested modules.
+ *
+ * @return the requested modules
+ */
+ public List<String> getRequestedModules() {
+ return requestedModules;
+ }
+
+ /**
+ * Returns the list of import entries.
+ *
+ * @return the import entries
+ */
+ public List<ImportEntry> getImportEntries() {
+ return importEntries;
+ }
+
+ /**
+ * Returns the list of local export entries.
+ *
+ * @return the local export entries
+ */
+ public List<ExportEntry> getLocalExportEntries() {
+ return localExportEntries;
+ }
+
+ /**
+ * Returns the list of indirect export entries.
+ *
+ * @return the indirect export entries
+ */
+ public List<ExportEntry> getIndirectExportEntries() {
+ return indirectExportEntries;
+ }
+
+ /**
+ * Returns the list of star export entries.
+ *
+ * @return the star export entries
+ */
+ public List<ExportEntry> getStarExportEntries() {
+ return starExportEntries;
+ }
+
+ @Override
+ public String toString() {
+ return "Module [requestedModules=" + requestedModules + ", importEntries=" + importEntries + ", localExportEntries=" + localExportEntries + ", indirectExportEntries=" +
+ indirectExportEntries + ", starExportEntries=" + starExportEntries + "]";
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java Fri May 06 06:23:30 2016 -0700
@@ -36,7 +36,7 @@
private static final long serialVersionUID = 1L;
/** Property key. */
- private final PropertyKey key;
+ private final Expression key;
/** Property value. */
private final Expression value;
@@ -47,6 +47,12 @@
/** Property getter. */
private final FunctionNode setter;
+ /** static property flag */
+ private final boolean isStatic;
+
+ /** Computed property flag */
+ private final boolean computed;
+
/**
* Constructor
*
@@ -56,21 +62,27 @@
* @param value the value of this property
* @param getter getter function body
* @param setter setter function body
+ * @param isStatic is this a static property?
+ * @param computed is this a computed property?
*/
- public PropertyNode(final long token, final int finish, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
+ public PropertyNode(final long token, final int finish, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) {
super(token, finish);
this.key = key;
this.value = value;
this.getter = getter;
this.setter = setter;
+ this.isStatic = isStatic;
+ this.computed = computed;
}
- private PropertyNode(final PropertyNode propertyNode, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
+ private PropertyNode(final PropertyNode propertyNode, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) {
super(propertyNode);
this.key = key;
this.value = value;
this.getter = getter;
this.setter = setter;
+ this.isStatic = isStatic;
+ this.computed = computed;
}
/**
@@ -78,14 +90,14 @@
* @return key name
*/
public String getKeyName() {
- return key.getPropertyName();
+ return key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : null;
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterPropertyNode(this)) {
return visitor.leavePropertyNode(
- setKey((PropertyKey)((Node)key).accept(visitor)).
+ setKey((Expression) key.accept(visitor)).
setValue(value == null ? null : (Expression)value.accept(visitor)).
setGetter(getter == null ? null : (FunctionNode)getter.accept(visitor)).
setSetter(setter == null ? null : (FunctionNode)setter.accept(visitor)));
@@ -134,7 +146,7 @@
if (this.getter == getter) {
return this;
}
- return new PropertyNode(this, key, value, getter, setter);
+ return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
@@ -142,14 +154,14 @@
* @return the key
*/
public Expression getKey() {
- return (Expression)key;
+ return key;
}
- private PropertyNode setKey(final PropertyKey key) {
+ private PropertyNode setKey(final Expression key) {
if (this.key == key) {
return this;
}
- return new PropertyNode(this, key, value, getter, setter);
+ return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
@@ -169,7 +181,7 @@
if (this.setter == setter) {
return this;
}
- return new PropertyNode(this, key, value, getter, setter);
+ return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
@@ -189,6 +201,24 @@
if (this.value == value) {
return this;
}
- return new PropertyNode(this, key, value, getter, setter);
- }
+ return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
+ }
+
+ /**
+ * Returns true if this is a static property.
+ *
+ * @return true if static flag is set
+ */
+ public boolean isStatic() {
+ return isStatic;
+ }
+
+ /**
+ * Returns true if this is a computed property.
+ *
+ * @return true if the computed flag is set
+ */
+ public boolean isComputed() {
+ return computed;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Fri May 06 06:23:30 2016 -0700
@@ -133,8 +133,8 @@
return enterASSIGN_SHR(binaryNode);
case ASSIGN_SUB:
return enterASSIGN_SUB(binaryNode);
- case BIND:
- return enterBIND(binaryNode);
+ case ARROW:
+ return enterARROW(binaryNode);
case BIT_AND:
return enterBIT_AND(binaryNode);
case BIT_OR:
@@ -217,8 +217,8 @@
return leaveASSIGN_SHR(binaryNode);
case ASSIGN_SUB:
return leaveASSIGN_SUB(binaryNode);
- case BIND:
- return leaveBIND(binaryNode);
+ case ARROW:
+ return leaveARROW(binaryNode);
case BIT_AND:
return leaveBIT_AND(binaryNode);
case BIT_OR:
@@ -735,22 +735,22 @@
}
/**
- * Binary enter - callback for entering a bind operator
+ * Binary enter - callback for entering a arrow operator
*
* @param binaryNode the node
* @return true if traversal should continue and node children be traversed, false otherwise
*/
- public boolean enterBIND(final BinaryNode binaryNode) {
+ public boolean enterARROW(final BinaryNode binaryNode) {
return enterDefault(binaryNode);
}
/**
- * Binary leave - callback for leaving a bind operator
+ * Binary leave - callback for leaving a arrow operator
*
* @param binaryNode the node
* @return processed node, which will replace the original one, or the original node
*/
- public Node leaveBIND(final BinaryNode binaryNode) {
+ public Node leaveARROW(final BinaryNode binaryNode) {
return leaveDefault(binaryNode);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Fri May 06 06:23:30 2016 -0700
@@ -33,6 +33,7 @@
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ClassNode;
import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.DebuggerNode;
import jdk.nashorn.internal.ir.EmptyNode;
@@ -897,5 +898,23 @@
return leaveDefault(withNode);
}
+ /**
+ * Callback for entering a ClassNode
+ *
+ * @param classNode the node
+ * @return true if traversal should continue and node children be traversed, false otherwise
+ */
+ public boolean enterClassNode(final ClassNode classNode) {
+ return enterDefault(classNode);
+ }
+ /**
+ * Callback for leaving a ClassNode
+ *
+ * @param classNode the node
+ * @return processed node, which will replace the original one, or the original node
+ */
+ public Node leaveClassNode(final ClassNode classNode) {
+ return leaveDefault(classNode);
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Fri May 06 06:23:30 2016 -0700
@@ -28,35 +28,55 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
+import static jdk.nashorn.internal.parser.TokenType.ARROW;
import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
import static jdk.nashorn.internal.parser.TokenType.CASE;
import static jdk.nashorn.internal.parser.TokenType.CATCH;
+import static jdk.nashorn.internal.parser.TokenType.CLASS;
import static jdk.nashorn.internal.parser.TokenType.COLON;
import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
+import static jdk.nashorn.internal.parser.TokenType.COMMENT;
import static jdk.nashorn.internal.parser.TokenType.CONST;
import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
+import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS;
import static jdk.nashorn.internal.parser.TokenType.ELSE;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
+import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT;
+import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
+import static jdk.nashorn.internal.parser.TokenType.EXPORT;
+import static jdk.nashorn.internal.parser.TokenType.EXTENDS;
import static jdk.nashorn.internal.parser.TokenType.FINALLY;
import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
import static jdk.nashorn.internal.parser.TokenType.IDENT;
import static jdk.nashorn.internal.parser.TokenType.IF;
+import static jdk.nashorn.internal.parser.TokenType.IMPORT;
import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
import static jdk.nashorn.internal.parser.TokenType.LBRACE;
+import static jdk.nashorn.internal.parser.TokenType.LBRACKET;
import static jdk.nashorn.internal.parser.TokenType.LET;
import static jdk.nashorn.internal.parser.TokenType.LPAREN;
+import static jdk.nashorn.internal.parser.TokenType.MUL;
+import static jdk.nashorn.internal.parser.TokenType.PERIOD;
import static jdk.nashorn.internal.parser.TokenType.RBRACE;
import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
import static jdk.nashorn.internal.parser.TokenType.RPAREN;
import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
+import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY;
+import static jdk.nashorn.internal.parser.TokenType.STATIC;
+import static jdk.nashorn.internal.parser.TokenType.STRING;
+import static jdk.nashorn.internal.parser.TokenType.SUPER;
import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
import static jdk.nashorn.internal.parser.TokenType.TERNARY;
+import static jdk.nashorn.internal.parser.TokenType.VAR;
+import static jdk.nashorn.internal.parser.TokenType.VOID;
import static jdk.nashorn.internal.parser.TokenType.WHILE;
+import static jdk.nashorn.internal.parser.TokenType.YIELD;
+import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR;
import java.io.Serializable;
import java.util.ArrayDeque;
@@ -68,6 +88,8 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.ir.AccessNode;
@@ -79,11 +101,13 @@
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ClassNode;
import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.DebuggerNode;
import jdk.nashorn.internal.ir.EmptyNode;
import jdk.nashorn.internal.ir.ErrorNode;
import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionList;
import jdk.nashorn.internal.ir.ExpressionStatement;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
@@ -92,7 +116,9 @@
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.Module;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ObjectNode;
import jdk.nashorn.internal.ir.PropertyKey;
@@ -110,6 +136,7 @@
import jdk.nashorn.internal.ir.WithNode;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
@@ -254,6 +281,14 @@
}
/**
+ * Set up first token. Skips opening EOL.
+ */
+ private void scanFirstToken() {
+ k = -1;
+ next();
+ }
+
+ /**
* Execute parse and return the resulting function node.
* Errors will be thrown and the error manager will contain information
* if parsing should fail
@@ -280,9 +315,7 @@
lexer.line = lexer.pendingLine = lineOffset + 1;
line = lineOffset;
- // Set up first token (skips opening EOL.)
- k = -1;
- next();
+ scanFirstToken();
// Begin parse.
return program(scriptName, allowPropertyFunction);
} catch (final Exception e) {
@@ -301,6 +334,44 @@
}
/**
+ * Parse and return the resulting module.
+ * Errors will be thrown and the error manager will contain information
+ * if parsing should fail
+ *
+ * @param moduleName name for the module, given to the parsed FunctionNode
+ * @param startPos start position in source
+ * @param len length of parse
+ *
+ * @return function node resulting from successful parse
+ */
+ public FunctionNode parseModule(final String moduleName, final int startPos, final int len) {
+ try {
+ stream = new TokenStream();
+ lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
+ lexer.line = lexer.pendingLine = lineOffset + 1;
+ line = lineOffset;
+
+ scanFirstToken();
+ // Begin parse.
+ return module(moduleName);
+ } catch (final Exception e) {
+ handleParseException(e);
+
+ return null;
+ }
+ }
+
+ /**
+ * Entry point for parsing a module.
+ *
+ * @param moduleName the module name
+ * @return the parsed module
+ */
+ public FunctionNode parseModule(final String moduleName) {
+ return parseModule(moduleName, 0, source.getLength());
+ }
+
+ /**
* Parse and return the list of function parameter list. A comma
* separated list of function parameter identifiers is expected to be parsed.
* Errors will be thrown and the error manager will contain information
@@ -314,11 +385,9 @@
stream = new TokenStream();
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
- // Set up first token (skips opening EOL.)
- k = -1;
- next();
-
- return formalParameterList(TokenType.EOF);
+ scanFirstToken();
+
+ return formalParameterList(TokenType.EOF, false);
} catch (final Exception e) {
handleParseException(e);
return null;
@@ -339,9 +408,7 @@
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
final int functionLine = line;
- // Set up first token (skips opening EOL.)
- k = -1;
- next();
+ scanFirstToken();
// Make a fake token for the function.
final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
@@ -432,7 +499,7 @@
}
// Skip to a recovery point.
-loop:
+ loop:
while (true) {
switch (type) {
case EOF:
@@ -474,7 +541,7 @@
sb.append(ident.getName());
final String name = namespace.uniqueName(sb.toString());
- assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name;
+ assert parentFunction != null || name.equals(PROGRAM.symbolName()) : "name = " + name;
int flags = 0;
if (isStrictMode) {
@@ -489,7 +556,8 @@
return functionNode;
}
- private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body){
+ private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) {
+ // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody();
// Start new block.
final FunctionNode functionNode =
new FunctionNode(
@@ -506,7 +574,9 @@
kind,
function.getFlags(),
body,
- function.getEndParserState());
+ function.getEndParserState(),
+ function.getModule(),
+ function.getDebugFlags());
printAST(functionNode);
@@ -544,23 +614,39 @@
expect(RBRACE);
}
- final int flags = newBlock.getFlags() | (needsBraces? 0 : Block.IS_SYNTHETIC);
+ final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC);
return new Block(blockToken, finish, flags, newBlock.getStatements());
}
+ /**
+ * Get the statements in a case clause.
+ */
+ private List<Statement> caseStatementList() {
+ final ParserContextBlockNode newBlock = newBlock();
+ try {
+ statementList();
+ } finally {
+ restoreBlock(newBlock);
+ }
+ return newBlock.getStatements();
+ }
/**
* Get all the statements generated by a single statement.
* @return Statements.
*/
private Block getStatement() {
+ return getStatement(false);
+ }
+
+ private Block getStatement(boolean labelledStatement) {
if (type == LBRACE) {
return getBlock(true);
}
// Set up new block. Captures first token.
final ParserContextBlockNode newBlock = newBlock();
try {
- statement(false, false, true);
+ statement(false, false, true, labelledStatement);
} finally {
restoreBlock(newBlock);
}
@@ -576,6 +662,9 @@
if (EVAL.symbolName().equals(name)) {
markEval(lc);
+ } else if (SUPER.getName().equals(name)) {
+ assert ident.isDirectSuper();
+ markSuperCall(lc);
}
}
@@ -585,7 +674,8 @@
*/
private void detectSpecialProperty(final IdentNode ident) {
if (isArguments(ident)) {
- lc.getCurrentFunction().setFlag(FunctionNode.USES_ARGUMENTS);
+ // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); }
+ getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS);
}
}
@@ -593,11 +683,15 @@
return env._es6;
}
+ private boolean isES6() {
+ return env._es6;
+ }
+
private static boolean isArguments(final String name) {
return ARGUMENTS_NAME.equals(name);
}
- private static boolean isArguments(final IdentNode ident) {
+ static boolean isArguments(final IdentNode ident) {
return isArguments(ident.getName());
}
@@ -634,20 +728,20 @@
case ASSIGN_SHL:
case ASSIGN_SHR:
case ASSIGN_SUB:
- if (!(lhs instanceof AccessNode ||
- lhs instanceof IndexNode ||
- lhs instanceof IdentNode)) {
- return referenceError(lhs, rhs, env._early_lvalue_error);
- }
-
if (lhs instanceof IdentNode) {
if (!checkIdentLValue((IdentNode)lhs)) {
return referenceError(lhs, rhs, false);
}
- verifyStrictIdent((IdentNode)lhs, "assignment");
+ verifyIdent((IdentNode)lhs, "assignment");
+ break;
+ } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) {
+ break;
+ } else if (opType == ASSIGN && isDestructuringLhs(lhs)) {
+ verifyDestructuringAssignmentPattern(lhs, "assignment");
+ break;
+ } else {
+ return referenceError(lhs, rhs, env._early_lvalue_error);
}
- break;
-
default:
break;
}
@@ -659,6 +753,114 @@
return new BinaryNode(op, lhs, rhs);
}
+ private boolean isDestructuringLhs(Expression lhs) {
+ if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) {
+ return isES6();
+ }
+ return false;
+ }
+
+ private void verifyDestructuringAssignmentPattern(Expression pattern, String contextString) {
+ assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
+ pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterLiteralNode(LiteralNode<?> literalNode) {
+ if (literalNode.isArray()) {
+ boolean restElement = false;
+ for (Expression element : literalNode.getElementExpressions()) {
+ if (element != null) {
+ if (restElement) {
+ throw error(String.format("Unexpected element after rest element"), element.getToken());
+ }
+ if (element.isTokenType(SPREAD_ARRAY)) {
+ restElement = true;
+ Expression lvalue = ((UnaryNode) element).getExpression();
+ if (!checkValidLValue(lvalue, contextString)) {
+ throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken());
+ }
+ }
+ element.accept(this);
+ }
+ }
+ return false;
+ } else {
+ return enterDefault(literalNode);
+ }
+ }
+
+ @Override
+ public boolean enterObjectNode(ObjectNode objectNode) {
+ return true;
+ }
+
+ @Override
+ public boolean enterPropertyNode(PropertyNode propertyNode) {
+ if (propertyNode.getValue() != null) {
+ propertyNode.getValue().accept(this);
+ return false;
+ } else {
+ return enterDefault(propertyNode);
+ }
+ }
+
+ @Override
+ public boolean enterIdentNode(IdentNode identNode) {
+ verifyIdent(identNode, contextString);
+ if (!checkIdentLValue(identNode)) {
+ referenceError(identNode, null, true);
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterAccessNode(AccessNode accessNode) {
+ return false;
+ }
+
+ @Override
+ public boolean enterIndexNode(IndexNode indexNode) {
+ return false;
+ }
+
+ @Override
+ public boolean enterBinaryNode(BinaryNode binaryNode) {
+ if (binaryNode.isTokenType(ASSIGN)) {
+ binaryNode.lhs().accept(this);
+ // Initializer(rhs) can be any AssignmentExpression
+ return false;
+ } else {
+ return enterDefault(binaryNode);
+ }
+ }
+
+ @Override
+ public boolean enterUnaryNode(UnaryNode unaryNode) {
+ if (unaryNode.isTokenType(SPREAD_ARRAY)) {
+ // rest element
+ return true;
+ } else {
+ return enterDefault(unaryNode);
+ }
+ }
+
+ @Override
+ protected boolean enterDefault(Node node) {
+ throw error(String.format("unexpected node in AssignmentPattern: %s", node));
+ }
+ });
+ }
+
+ private static Expression newBinaryExpression(final long op, final Expression lhs, final Expression rhs) {
+ final TokenType opType = Token.descType(op);
+
+ // Build up node.
+ if (BinaryNode.isLogical(opType)) {
+ return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
+ }
+ return new BinaryNode(op, lhs, rhs);
+ }
+
/**
* Reduce increment/decrement to simpler operations.
@@ -717,7 +919,7 @@
restoreBlock(body);
body.setFlag(Block.NEEDS_SCOPE);
- final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
+ final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
lc.pop(script);
script.setLastToken(token);
@@ -776,7 +978,7 @@
try {
// Get the next element.
- statement(true, allowPropertyFunction, false);
+ statement(true, allowPropertyFunction, false, false);
allowPropertyFunction = false;
// check for directive prologues
@@ -816,16 +1018,16 @@
// verify that function name as well as parameter names
// satisfy strict mode restrictions.
- verifyStrictIdent(function.getIdent(), "function name");
+ verifyIdent(function.getIdent(), "function name");
for (final IdentNode param : function.getParameters()) {
- verifyStrictIdent(param, "function parameter");
+ verifyIdent(param, "function parameter");
}
}
} else if (Context.DEBUG) {
- final int flag = FunctionNode.getDirectiveFlag(directive);
- if (flag != 0) {
+ final int debugFlag = FunctionNode.getDirectiveFlag(directive);
+ if (debugFlag != 0) {
final ParserContextFunctionNode function = lc.getCurrentFunction();
- function.setFlag(flag);
+ function.setDebugFlag(debugFlag);
}
}
}
@@ -849,29 +1051,53 @@
}
/**
+ * Parse any of the basic statement types.
+ *
* Statement :
- * Block
+ * BlockStatement
* VariableStatement
* EmptyStatement
* ExpressionStatement
* IfStatement
- * IterationStatement
+ * BreakableStatement
* ContinueStatement
* BreakStatement
* ReturnStatement
* WithStatement
* LabelledStatement
- * SwitchStatement
* ThrowStatement
* TryStatement
* DebuggerStatement
*
- * see 12
+ * BreakableStatement :
+ * IterationStatement
+ * SwitchStatement
+ *
+ * BlockStatement :
+ * Block
+ *
+ * Block :
+ * { StatementList opt }
*
- * Parse any of the basic statement types.
+ * StatementList :
+ * StatementListItem
+ * StatementList StatementListItem
+ *
+ * StatementItem :
+ * Statement
+ * Declaration
+ *
+ * Declaration :
+ * HoistableDeclaration
+ * ClassDeclaration
+ * LexicalDeclaration
+ *
+ * HoistableDeclaration :
+ * FunctionDeclaration
+ * GeneratorDeclaration
*/
private void statement() {
- statement(false, false, false);
+ statement(false, false, false, false);
}
/**
@@ -879,14 +1105,7 @@
* @param allowPropertyFunction allow property "get" and "set" functions?
* @param singleStatement are we in a single statement context?
*/
- private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
- if (type == FUNCTION) {
- // As per spec (ECMA section 12), function declarations as arbitrary statement
- // is not "portable". Implementation can issue a warning or disallow the same.
- functionExpression(true, topLevel);
- return;
- }
-
+ private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement, final boolean labelledStatement) {
switch (type) {
case LBRACE:
block();
@@ -918,9 +1137,6 @@
case RETURN:
returnStatement();
break;
- case YIELD:
- yieldStatement();
- break;
case WITH:
withStatement();
break;
@@ -941,13 +1157,32 @@
case EOF:
expect(SEMICOLON);
break;
+ case FUNCTION:
+ // As per spec (ECMA section 12), function declarations as arbitrary statement
+ // is not "portable". Implementation can issue a warning or disallow the same.
+ if (singleStatement) {
+ // ES6 B.3.2 Labelled Function Declarations
+ // It is a Syntax Error if any strict mode source code matches this rule:
+ // LabelledItem : FunctionDeclaration.
+ if (!labelledStatement || isStrictMode) {
+ throw error(AbstractParser.message("expected.stmt", "function declaration"), token);
+ }
+ }
+ functionExpression(true, topLevel || labelledStatement);
+ return;
default:
- if (useBlockScope() && (type == LET || type == CONST)) {
+ if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) {
if (singleStatement) {
throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
}
variableStatement(type);
break;
+ } else if (type == CLASS && isES6()) {
+ if (singleStatement) {
+ throw error(AbstractParser.message("expected.stmt", "class declaration"), token);
+ }
+ classDeclaration(false);
+ break;
}
if (env._const_as_var && type == CONST) {
variableStatement(TokenType.VAR);
@@ -963,11 +1198,11 @@
final String ident = (String)getValue();
final long propertyToken = token;
final int propertyLine = line;
- if("get".equals(ident)) {
+ if ("get".equals(ident)) {
next();
addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
return;
- } else if("set".equals(ident)) {
+ } else if ("set".equals(ident)) {
next();
addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
return;
@@ -986,6 +1221,267 @@
}
/**
+ * ClassDeclaration[Yield, Default] :
+ * class BindingIdentifier[?Yield] ClassTail[?Yield]
+ * [+Default] class ClassTail[?Yield]
+ */
+ private ClassNode classDeclaration(boolean isDefault) {
+ int classLineNumber = line;
+
+ ClassNode classExpression = classExpression(!isDefault);
+
+ if (!isDefault) {
+ VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST);
+ appendStatement(classVar);
+ }
+ return classExpression;
+ }
+
+ /**
+ * ClassExpression[Yield] :
+ * class BindingIdentifier[?Yield]opt ClassTail[?Yield]
+ */
+ private ClassNode classExpression(boolean isStatement) {
+ assert type == CLASS;
+ int classLineNumber = line;
+ long classToken = token;
+ next();
+
+ IdentNode className = null;
+ if (isStatement || type == IDENT) {
+ className = getIdent();
+ }
+
+ return classTail(classLineNumber, classToken, className);
+ }
+
+ private static final class ClassElementKey {
+ private final boolean isStatic;
+ private final String propertyName;
+
+ private ClassElementKey(boolean isStatic, String propertyName) {
+ this.isStatic = isStatic;
+ this.propertyName = propertyName;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (isStatic ? 1231 : 1237);
+ result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ClassElementKey) {
+ ClassElementKey other = (ClassElementKey) obj;
+ return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Parse ClassTail and ClassBody.
+ *
+ * ClassTail[Yield] :
+ * ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
+ * ClassHeritage[Yield] :
+ * extends LeftHandSideExpression[?Yield]
+ *
+ * ClassBody[Yield] :
+ * ClassElementList[?Yield]
+ * ClassElementList[Yield] :
+ * ClassElement[?Yield]
+ * ClassElementList[?Yield] ClassElement[?Yield]
+ * ClassElement[Yield] :
+ * MethodDefinition[?Yield]
+ * static MethodDefinition[?Yield]
+ * ;
+ */
+ private ClassNode classTail(final int classLineNumber, final long classToken, final IdentNode className) {
+ final boolean oldStrictMode = isStrictMode;
+ isStrictMode = true;
+ try {
+ Expression classHeritage = null;
+ if (type == EXTENDS) {
+ next();
+ classHeritage = leftHandSideExpression();
+ }
+
+ expect(LBRACE);
+
+ PropertyNode constructor = null;
+ final ArrayList<PropertyNode> classElements = new ArrayList<>();
+ final Map<ClassElementKey, Integer> keyToIndexMap = new HashMap<>();
+ for (;;) {
+ if (type == SEMICOLON) {
+ next();
+ continue;
+ }
+ if (type == RBRACE) {
+ break;
+ }
+ final long classElementToken = token;
+ boolean isStatic = false;
+ if (type == STATIC) {
+ isStatic = true;
+ next();
+ }
+ boolean generator = false;
+ if (isES6() && type == MUL) {
+ generator = true;
+ next();
+ }
+ final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator);
+ if (classElement.isComputed()) {
+ classElements.add(classElement);
+ } else if (!classElement.isStatic() && classElement.getKeyName().equals("constructor")) {
+ if (constructor == null) {
+ constructor = classElement;
+ } else {
+ throw error(AbstractParser.message("multiple.constructors"), classElementToken);
+ }
+ } else {
+ // Check for duplicate method definitions and combine accessor methods.
+ // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names).
+
+ final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName());
+ final Integer existing = keyToIndexMap.get(key);
+
+ if (existing == null) {
+ keyToIndexMap.put(key, classElements.size());
+ classElements.add(classElement);
+ } else {
+ final PropertyNode existingProperty = classElements.get(existing);
+
+ final Expression value = classElement.getValue();
+ final FunctionNode getter = classElement.getGetter();
+ final FunctionNode setter = classElement.getSetter();
+
+ if (value != null || existingProperty.getValue() != null) {
+ keyToIndexMap.put(key, classElements.size());
+ classElements.add(classElement);
+ } else if (getter != null) {
+ assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
+ classElements.set(existing, existingProperty.setGetter(getter));
+ } else if (setter != null) {
+ assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
+ classElements.set(existing, existingProperty.setSetter(setter));
+ }
+ }
+ }
+ }
+
+ final long lastToken = token;
+ expect(RBRACE);
+
+ if (constructor == null) {
+ constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null);
+ }
+
+ classElements.trimToSize();
+ return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements);
+ } finally {
+ isStrictMode = oldStrictMode;
+ }
+ }
+
+ private PropertyNode createDefaultClassConstructor(int classLineNumber, long classToken, long lastToken, IdentNode className, boolean subclass) {
+ final int ctorFinish = finish;
+ final List<Statement> statements;
+ final List<IdentNode> parameters;
+ final long identToken = Token.recast(classToken, TokenType.IDENT);
+ if (subclass) {
+ final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper();
+ final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter();
+ final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent);
+ final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false);
+ statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall));
+ parameters = Collections.singletonList(argsIdent);
+ } else {
+ statements = Collections.emptyList();
+ parameters = Collections.emptyList();
+ }
+
+ final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements);
+ final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, "constructor");
+ final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters);
+ function.setLastToken(lastToken);
+
+ function.setFlag(FunctionNode.ES6_IS_METHOD);
+ function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR);
+ if (subclass) {
+ function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR);
+ function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
+ }
+ if (className == null) {
+ function.setFlag(FunctionNode.IS_ANONYMOUS);
+ }
+
+ final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode(
+ function,
+ classToken,
+ ctorName,
+ parameters,
+ FunctionNode.Kind.NORMAL,
+ classLineNumber,
+ body
+ ), null, null, false, false);
+ return constructor;
+ }
+
+ private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) {
+ final long methodToken = token;
+ final int methodLine = line;
+ final boolean computed = type == LBRACKET;
+ final boolean isIdent = type == IDENT;
+ final Expression propertyName = propertyName();
+ int flags = FunctionNode.ES6_IS_METHOD;
+ if (!computed) {
+ final String name = ((PropertyKey)propertyName).getPropertyName();
+ if (!generator && isIdent && type != LPAREN && name.equals("get")) {
+ final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags);
+ verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
+ return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed);
+ } else if (!generator && isIdent && type != LPAREN && name.equals("set")) {
+ final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags);
+ verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
+ return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed);
+ } else {
+ if (!isStatic && !generator && name.equals("constructor")) {
+ flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR;
+ if (subclass) {
+ flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR;
+ }
+ }
+ verifyAllowedMethodName(propertyName, isStatic, computed, generator, false);
+ }
+ }
+ final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed);
+ return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed);
+ }
+
+ /**
+ * ES6 14.5.1 Static Semantics: Early Errors.
+ */
+ private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) {
+ if (!computed) {
+ if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals("constructor")) {
+ throw error(AbstractParser.message("generator.constructor"), key.getToken());
+ }
+ if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals("constructor")) {
+ throw error(AbstractParser.message("accessor.constructor"), key.getToken());
+ }
+ if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) {
+ throw error(AbstractParser.message("static.prototype.method"), key.getToken());
+ }
+ }
+ }
+
+ /**
* block :
* { StatementList? }
*
@@ -1008,7 +1504,7 @@
*/
private void statementList() {
// Accumulate statements until end of list. */
-loop:
+ loop:
while (type != EOF) {
switch (type) {
case EOF:
@@ -1026,6 +1522,22 @@
}
/**
+ * Make sure that the identifier name used is allowed.
+ *
+ * @param ident Identifier that is verified
+ * @param contextString String used in error message to give context to the user
+ */
+ private void verifyIdent(final IdentNode ident, final String contextString) {
+ verifyStrictIdent(ident, contextString);
+ if (isES6()) {
+ final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
+ if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
+ throw error(expectMessage(IDENT));
+ }
+ }
+ }
+
+ /**
* Make sure that in strict mode, the identifier name used is allowed.
*
* @param ident Identifier that is verified
@@ -1066,15 +1578,16 @@
* Parse a VAR statement.
* @param isStatement True if a statement (not used in a FOR.)
*/
- private List<VarNode> variableStatement(final TokenType varType) {
- return variableStatement(varType, true, -1);
+ private void variableStatement(final TokenType varType) {
+ variableDeclarationList(varType, true, -1);
}
- private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
+ private List<Expression> variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
// VAR tested in caller.
+ assert varType == VAR || varType == LET || varType == CONST;
next();
- final List<VarNode> vars = new ArrayList<>();
+ final List<Expression> bindings = new ArrayList<>();
int varFlags = 0;
if (varType == LET) {
varFlags |= VarNode.IS_LET;
@@ -1082,13 +1595,29 @@
varFlags |= VarNode.IS_CONST;
}
+ Expression missingAssignment = null;
while (true) {
// Get starting token.
final int varLine = line;
final long varToken = token;
// Get name of var.
- final IdentNode name = getIdent();
- verifyStrictIdent(name, "variable name");
+ if (type == YIELD && inGeneratorFunction()) {
+ expect(IDENT);
+ }
+
+ final String contextString = "variable name";
+ Expression binding = bindingIdentifierOrPattern(contextString);
+ final boolean isDestructuring = !(binding instanceof IdentNode);
+ if (isDestructuring) {
+ final int finalVarFlags = varFlags;
+ verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
+ public void accept(final IdentNode identNode) {
+ verifyIdent(identNode, contextString);
+ final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
+ appendStatement(var);
+ }
+ });
+ }
// Assume no init.
Expression init = null;
@@ -1098,22 +1627,53 @@
next();
// Get initializer expression. Suppress IN if not statement.
- defaultNames.push(name);
+ if (!isDestructuring) {
+ defaultNames.push(binding);
+ }
try {
init = assignmentExpression(!isStatement);
} finally {
- defaultNames.pop();
+ if (!isDestructuring) {
+ defaultNames.pop();
+ }
}
- } else if (varType == CONST && isStatement) {
- throw error(AbstractParser.message("missing.const.assignment", name.getName()));
+ } else if (isStatement) {
+ if (isDestructuring) {
+ throw error(AbstractParser.message("missing.destructuring.assignment"), token);
+ } else if (varType == CONST) {
+ throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName()));
+ }
+ // else, if we are in a for loop, delay checking until we know the kind of loop
}
- // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
- final IdentNode actualName = varType == LET || varType == CONST ? name.setIsDeclaredHere() : name;
- // Allocate var node.
- final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, actualName, init, varFlags);
- vars.add(var);
- appendStatement(var);
+ if (!isDestructuring) {
+ assert init != null || varType != CONST || !isStatement;
+ final IdentNode ident = (IdentNode)binding;
+ if (!isStatement && ident.getName().equals("let")) {
+ throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1
+ }
+ // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
+ final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident;
+ binding = name;
+ final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags);
+ appendStatement(var);
+ if (init == null && varType == CONST) {
+ if (missingAssignment == null) {
+ missingAssignment = binding;
+ }
+ }
+ } else {
+ assert init != null || !isStatement;
+ binding = init == null ? binding : verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
+ if (isStatement) {
+ appendStatement(new ExpressionStatement(varLine, binding.getToken(), finish, binding));
+ } else if (init == null) {
+ if (missingAssignment == null) {
+ missingAssignment = binding;
+ }
+ }
+ }
+ bindings.add(binding);
if (type != COMMARIGHT) {
break;
@@ -1124,9 +1684,128 @@
// If is a statement then handle end of line.
if (isStatement) {
endOfLine();
+ } else {
+ if (type == SEMICOLON) {
+ // late check for missing assignment, now we know it's a for (init; test; modify) loop
+ if (missingAssignment != null) {
+ if (missingAssignment instanceof IdentNode) {
+ throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)missingAssignment).getName()));
+ } else {
+ throw error(AbstractParser.message("missing.destructuring.assignment"), missingAssignment.getToken());
+ }
+ }
+ }
}
- return vars;
+ return bindings;
+ }
+
+ private boolean isBindingIdentifier() {
+ return type == IDENT || isNonStrictModeIdent();
+ }
+
+ private IdentNode bindingIdentifier(final String contextString) {
+ final IdentNode name = getIdent();
+ verifyIdent(name, contextString);
+ return name;
+ }
+
+ private Expression bindingPattern() {
+ if (type == LBRACKET) {
+ return arrayLiteral();
+ } else if (type == LBRACE) {
+ return objectLiteral();
+ } else {
+ throw error(AbstractParser.message("expected.binding"));
+ }
+ }
+
+ private Expression bindingIdentifierOrPattern(final String contextString) {
+ if (isBindingIdentifier() || !isES6()) {
+ return bindingIdentifier(contextString);
+ } else {
+ return bindingPattern();
+ }
+ }
+
+ /**
+ * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
+ */
+ private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
+ assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
+ pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
+ if (literalNode.isArray()) {
+ boolean restElement = false;
+ for (final Expression element : literalNode.getElementExpressions()) {
+ if (restElement) {
+ throw error(String.format("Unexpected element after rest element"), element.getToken());
+ }
+ if (element != null) {
+ if (element.isTokenType(SPREAD_ARRAY)) {
+ restElement = true;
+ if (!(((UnaryNode) element).getExpression() instanceof IdentNode)) {
+ throw error(String.format("Expected a valid binding identifier"), element.getToken());
+
+ }
+ }
+ element.accept(this);
+ }
+ }
+ return false;
+ } else {
+ return enterDefault(literalNode);
+ }
+ }
+
+ @Override
+ public boolean enterObjectNode(final ObjectNode objectNode) {
+ return true;
+ }
+
+ @Override
+ public boolean enterPropertyNode(final PropertyNode propertyNode) {
+ if (propertyNode.getValue() != null) {
+ propertyNode.getValue().accept(this);
+ return false;
+ } else {
+ return enterDefault(propertyNode);
+ }
+ }
+
+ @Override
+ public boolean enterIdentNode(final IdentNode identNode) {
+ identifierCallback.accept(identNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterBinaryNode(final BinaryNode binaryNode) {
+ if (binaryNode.isTokenType(ASSIGN)) {
+ binaryNode.lhs().accept(this);
+ // Initializer(rhs) can be any AssignmentExpression
+ return false;
+ } else {
+ return enterDefault(binaryNode);
+ }
+ }
+
+ @Override
+ public boolean enterUnaryNode(final UnaryNode unaryNode) {
+ if (unaryNode.isTokenType(SPREAD_ARRAY)) {
+ // rest element
+ return true;
+ } else {
+ return enterDefault(unaryNode);
+ }
+ }
+
+ @Override
+ protected boolean enterDefault(final Node node) {
+ throw error(String.format("unexpected node in BindingPattern: %s", node));
+ }
+ });
}
/**
@@ -1230,7 +1909,7 @@
final ParserContextLoopNode forNode = new ParserContextLoopNode();
lc.push(forNode);
Block body = null;
- List<VarNode> vars = null;
+ List<Expression> vars = null;
Expression init = null;
JoinPredecessorExpression test = null;
JoinPredecessorExpression modify = null;
@@ -1254,20 +1933,20 @@
switch (type) {
case VAR:
// Var declaration captured in for outer block.
- vars = variableStatement(type, false, forStart);
+ vars = variableDeclarationList(type, false, forStart);
break;
case SEMICOLON:
break;
default:
- if (useBlockScope() && (type == LET || type == CONST)) {
+ if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) {
flags |= ForNode.PER_ITERATION_SCOPE;
// LET/CONST declaration captured in container block created above.
- vars = variableStatement(type, false, forStart);
+ vars = variableDeclarationList(type, false, forStart);
break;
}
if (env._const_as_var && type == CONST) {
// Var declaration captured in for outer block.
- vars = variableStatement(TokenType.VAR, false, forStart);
+ vars = variableDeclarationList(TokenType.VAR, false, forStart);
break;
}
@@ -1309,7 +1988,11 @@
if (vars != null) {
// for (var i in obj)
if (vars.size() == 1) {
- init = new IdentNode(vars.get(0).getName());
+ init = new IdentNode((IdentNode)vars.get(0));
+ if (init.isTokenType(ASSIGN)) {
+ throw error(AbstractParser.message("for.in.loop.initializer"), init.getToken());
+ }
+ assert init instanceof IdentNode || isDestructuringLhs(init);
} else {
// for (var i, j in obj) is invalid
throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
@@ -1351,10 +2034,9 @@
} finally {
lc.pop(forNode);
- if (vars != null) {
- for (final VarNode var : vars) {
- appendStatement(var);
- }
+ for (final Statement var : forNode.getStatements()) {
+ assert var instanceof VarNode;
+ appendStatement(var);
}
if (body != null) {
appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
@@ -1371,6 +2053,49 @@
}
}
+ private boolean checkValidLValue(final Expression init, final String contextString) {
+ if (init instanceof IdentNode) {
+ if (!checkIdentLValue((IdentNode)init)) {
+ return false;
+ }
+ verifyIdent((IdentNode)init, contextString);
+ return true;
+ } else if (init instanceof AccessNode || init instanceof IndexNode) {
+ return true;
+ } else if (isDestructuringLhs(init)) {
+ verifyDestructuringAssignmentPattern(init, contextString);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
+ assert type == LET;
+ for (int i = 1;; i++) {
+ TokenType t = T(k + i);
+ switch (t) {
+ case EOL:
+ case COMMENT:
+ continue;
+ case IDENT:
+ if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
+ return false;
+ }
+ // fall through
+ case LBRACKET:
+ case LBRACE:
+ return true;
+ default:
+ // accept future strict tokens in non-strict mode (including LET)
+ if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+
/**
* ...IterationStatement :
* ...
@@ -1559,7 +2284,7 @@
*/
private void returnStatement() {
// check for return outside function
- if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
+ if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
throw error(AbstractParser.message("invalid.return"));
}
@@ -1591,39 +2316,61 @@
}
/**
- * YieldStatement :
- * yield Expression? ; // [no LineTerminator here]
- *
- * JavaScript 1.8
+ * Parse YieldExpression.
*
- * Parse YIELD statement.
+ * YieldExpression[In] :
+ * yield
+ * yield [no LineTerminator here] AssignmentExpression[?In, Yield]
+ * yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
*/
- private void yieldStatement() {
+ private Expression yieldExpression(final boolean noIn) {
+ assert inGeneratorFunction();
// Capture YIELD token.
- final int yieldLine = line;
- final long yieldToken = token;
+ long yieldToken = token;
// YIELD tested in caller.
+ assert type == YIELD;
nextOrEOL();
Expression expression = null;
- // SEMICOLON or expression.
+ boolean yieldAsterisk = false;
+ if (type == MUL) {
+ yieldAsterisk = true;
+ yieldToken = Token.recast(yieldToken, YIELD_STAR);
+ next();
+ }
+
switch (type) {
case RBRACE:
case SEMICOLON:
case EOL:
case EOF:
- break;
+ case COMMARIGHT:
+ case RPAREN:
+ case RBRACKET:
+ case COLON:
+ if (!yieldAsterisk) {
+ // treat (yield) as (yield void 0)
+ expression = newUndefinedLiteral(yieldToken, finish);
+ if (type == EOL) {
+ next();
+ }
+ break;
+ } else {
+ // AssignmentExpression required, fall through
+ }
default:
- expression = expression();
+ expression = assignmentExpression(noIn);
break;
}
- endOfLine();
-
// Construct and add YIELD node.
- appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
+ return new UnaryNode(yieldToken, expression);
+ }
+
+ private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
+ return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
}
/**
@@ -1679,11 +2426,15 @@
private void switchStatement() {
final int switchLine = line;
final long switchToken = token;
+
+ // Block to capture variables declared inside the switch statement.
+ final ParserContextBlockNode switchBlock = newBlock();
+
// SWITCH tested in caller.
next();
// Create and add switch statement.
- final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
+ final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
lc.push(switchNode);
CaseNode defaultCase = null;
@@ -1727,7 +2478,7 @@
expect(COLON);
// Get CASE body.
- final Block statements = getBlock(false);
+ final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
if (caseExpression == null) {
@@ -1740,9 +2491,11 @@
next();
} finally {
lc.pop(switchNode);
+ restoreBlock(switchBlock);
}
- appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
+ final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
+ appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
}
/**
@@ -1769,7 +2522,7 @@
Block body = null;
try {
lc.push(labelNode);
- body = getStatement();
+ body = getStatement(true);
} finally {
assert lc.peek() instanceof ParserContextLabelNode;
lc.pop(labelNode);
@@ -1935,13 +2688,19 @@
/**
* PrimaryExpression :
* this
- * Identifier
+ * IdentifierReference
* Literal
* ArrayLiteral
* ObjectLiteral
* RegularExpressionLiteral
* TemplateLiteral
+ * CoverParenthesizedExpressionAndArrowParameterList
+ *
+ * CoverParenthesizedExpressionAndArrowParameterList :
* ( Expression )
+ * ( )
+ * ( ... BindingIdentifier )
+ * ( Expression , ... BindingIdentifier )
*
* Parse primary expression.
* @return Expression node.
@@ -1956,7 +2715,7 @@
case THIS:
final String name = type.getName();
next();
- lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
+ markThis(lc);
return new IdentNode(primaryToken, finish, name);
case IDENT:
final IdentNode ident = getIdent();
@@ -1997,6 +2756,22 @@
case LPAREN:
next();
+ if (isES6()) {
+ if (type == RPAREN) {
+ // ()
+ nextOrEOL();
+ expectDontAdvance(ARROW);
+ return new ExpressionList(primaryToken, finish, Collections.emptyList());
+ } else if (type == ELLIPSIS) {
+ // (...rest)
+ final IdentNode restParam = formalParameterList(false).get(0);
+ expectDontAdvance(RPAREN);
+ nextOrEOL();
+ expectDontAdvance(ARROW);
+ return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
+ }
+ }
+
final Expression expression = expression();
expect(RPAREN);
@@ -2073,8 +2848,9 @@
final List<Expression> elements = new ArrayList<>();
// Track elisions.
boolean elision = true;
-loop:
+ loop:
while (true) {
+ long spreadToken = 0;
switch (type) {
case RBRACKET:
next();
@@ -2093,14 +2869,24 @@
break;
+ case ELLIPSIS:
+ if (isES6()) {
+ spreadToken = token;
+ next();
+ }
+ // fall through
+
default:
if (!elision) {
throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
}
+
// Add expression element.
- final Expression expression = assignmentExpression(false);
-
+ Expression expression = assignmentExpression(false);
if (expression != null) {
+ if (spreadToken != 0) {
+ expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
+ }
elements.add(expression);
} else {
expect(RBRACKET);
@@ -2141,7 +2927,7 @@
// Create a block for the object literal.
boolean commaSeen = true;
-loop:
+ loop:
while (true) {
switch (type) {
case RBRACE:
@@ -2164,6 +2950,12 @@
commaSeen = false;
// Get and add the next property.
final PropertyNode property = propertyAssignment();
+
+ if (property.isComputed()) {
+ elements.add(property);
+ break;
+ }
+
final String key = property.getKeyName();
final Integer existing = map.get(key);
@@ -2185,36 +2977,23 @@
final FunctionNode prevGetter = existingProperty.getGetter();
final FunctionNode prevSetter = existingProperty.getSetter();
- // ECMA 11.1.5 strict mode restrictions
- if (isStrictMode && value != null && prevValue != null) {
- throw error(AbstractParser.message("property.redefinition", key), property.getToken());
- }
-
- final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
- final boolean isAccessor = getter != null || setter != null;
-
- // data property redefined as accessor property
- if (prevValue != null && isAccessor) {
- throw error(AbstractParser.message("property.redefinition", key), property.getToken());
- }
-
- // accessor property redefined as data
- if (isPrevAccessor && value != null) {
- throw error(AbstractParser.message("property.redefinition", key), property.getToken());
- }
-
- if (isAccessor && isPrevAccessor) {
- if (getter != null && prevGetter != null ||
- setter != null && prevSetter != null) {
- throw error(AbstractParser.message("property.redefinition", key), property.getToken());
+ if (!isES6()) {
+ checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
+ } else {
+ if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
+ existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
+ throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
}
}
- if (value != null) {
+ if (value != null || prevValue != null) {
+ map.put(key, elements.size());
elements.add(property);
} else if (getter != null) {
+ assert prevGetter != null || prevSetter != null;
elements.set(existing, existingProperty.setGetter(getter));
} else if (setter != null) {
+ assert prevGetter != null || prevSetter != null;
elements.set(existing, existingProperty.setSetter(setter));
}
break;
@@ -2224,18 +3003,43 @@
return new ObjectNode(objectToken, finish, elements);
}
+ private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
+ // ECMA 11.1.5 strict mode restrictions
+ if (isStrictMode && value != null && prevValue != null) {
+ throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+ }
+
+ final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
+ final boolean isAccessor = getter != null || setter != null;
+
+ // data property redefined as accessor property
+ if (prevValue != null && isAccessor) {
+ throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+ }
+
+ // accessor property redefined as data
+ if (isPrevAccessor && value != null) {
+ throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+ }
+
+ if (isAccessor && isPrevAccessor) {
+ if (getter != null && prevGetter != null ||
+ setter != null && prevSetter != null) {
+ throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+ }
+ }
+ }
+
/**
- * PropertyName :
+ * LiteralPropertyName :
* IdentifierName
* StringLiteral
* NumericLiteral
*
- * See 11.1.5
- *
* @return PropertyName node
*/
@SuppressWarnings("fallthrough")
- private PropertyKey propertyName() {
+ private PropertyKey literalPropertyName() {
switch (type) {
case IDENT:
return getIdent().setIsPropertyName();
@@ -2257,6 +3061,34 @@
}
/**
+ * ComputedPropertyName :
+ * AssignmentExpression
+ *
+ * @return PropertyName node
+ */
+ private Expression computedPropertyName() {
+ expect(LBRACKET);
+ Expression expression = assignmentExpression(false);
+ expect(RBRACKET);
+ return expression;
+ }
+
+ /**
+ * PropertyName :
+ * LiteralPropertyName
+ * ComputedPropertyName
+ *
+ * @return PropertyName node
+ */
+ private Expression propertyName() {
+ if (type == LBRACKET && isES6()) {
+ return computedPropertyName();
+ } else {
+ return (Expression)literalPropertyName();
+ }
+ }
+
+ /**
* PropertyAssignment :
* PropertyName : AssignmentExpression
* get PropertyName ( ) { FunctionBody }
@@ -2280,51 +3112,95 @@
final long propertyToken = token;
final int functionLine = line;
- PropertyKey propertyName;
-
+ final Expression propertyName;
+ final boolean isIdentifier;
+
+ boolean generator = false;
+ if (type == MUL && isES6()) {
+ generator = true;
+ next();
+ }
+
+ final boolean computed = type == LBRACKET;
if (type == IDENT) {
// Get IDENT.
final String ident = (String)expectValue(IDENT);
- if (type != COLON) {
+ if (type != COLON && (type != LPAREN || !isES6())) {
final long getSetToken = propertyToken;
switch (ident) {
case "get":
final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
- return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
+ return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
case "set":
final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
- return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
+ return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
default:
break;
}
}
- propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
+ isIdentifier = true;
+ IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
+ if (type == COLON && ident.equals("__proto__")) {
+ identNode = identNode.setIsProtoPropertyName();
+ }
+ propertyName = identNode;
} else {
+ isIdentifier = isNonStrictModeIdent();
propertyName = propertyName();
}
- expect(COLON);
-
- defaultNames.push(propertyName);
- try {
- return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
- } finally {
- defaultNames.pop();
+ Expression propertyValue;
+
+ if (generator) {
+ expectDontAdvance(LPAREN);
}
+
+ if (type == LPAREN && isES6()) {
+ propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
+ } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
+ propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
+ if (type == ASSIGN && isES6()) {
+ // TODO if not destructuring, this is a SyntaxError
+ final long assignToken = token;
+ next();
+ final Expression rhs = assignmentExpression(false);
+ propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
+ }
+ } else {
+ expect(COLON);
+
+ defaultNames.push(propertyName);
+ try {
+ propertyValue = assignmentExpression(false);
+ } finally {
+ defaultNames.pop();
+ }
+ }
+
+ return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
}
private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
- final PropertyKey getIdent = propertyName();
- final String getterName = getIdent.getPropertyName();
- final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
+ return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
+ }
+
+ private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
+ final boolean computed = type == LBRACKET;
+ final Expression propertyName = propertyName();
+ final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
+ final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
expect(LPAREN);
expect(RPAREN);
final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
+ functionNode.setFlag(flags);
+ if (computed) {
+ functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+ }
lc.push(functionNode);
Block functionBody;
@@ -2345,20 +3221,25 @@
functionLine,
functionBody);
- return new PropertyFunction(getIdent, function);
+ return new PropertyFunction(propertyName, function, computed);
}
private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
- final PropertyKey setIdent = propertyName();
- final String setterName = setIdent.getPropertyName();
- final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
+ return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
+ }
+
+ private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
+ final boolean computed = type == LBRACKET;
+ final Expression propertyName = propertyName();
+ final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
+ final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
expect(LPAREN);
// be sloppy and allow missing setter parameter even though
// spec does not permit it!
final IdentNode argIdent;
- if (type == IDENT || isNonStrictModeIdent()) {
+ if (isBindingIdentifier()) {
argIdent = getIdent();
- verifyStrictIdent(argIdent, "setter argument");
+ verifyIdent(argIdent, "setter argument");
} else {
argIdent = null;
}
@@ -2370,6 +3251,10 @@
final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
+ functionNode.setFlag(flags);
+ if (computed) {
+ functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+ }
lc.push(functionNode);
Block functionBody;
@@ -2389,33 +3274,81 @@
functionLine,
functionBody);
- return new PropertyFunction(setIdent, function);
+ return new PropertyFunction(propertyName, function, computed);
+ }
+
+ private PropertyFunction propertyMethodFunction(Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, boolean computed) {
+ final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
+ final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
+
+ FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
+ final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
+ functionNode.setFlag(flags);
+ if (computed) {
+ functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+ }
+ lc.push(functionNode);
+
+ try {
+ final ParserContextBlockNode parameterBlock = newBlock();
+ final List<IdentNode> parameters;
+ try {
+ expect(LPAREN);
+ parameters = formalParameterList(generator);
+ functionNode.setParameters(parameters);
+ expect(RPAREN);
+ } finally {
+ restoreBlock(parameterBlock);
+ }
+
+ Block functionBody = functionBody(functionNode);
+
+ functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
+
+ final FunctionNode function = createFunctionNode(
+ functionNode,
+ methodToken,
+ methodNameNode,
+ parameters,
+ functionKind,
+ methodLine,
+ functionBody);
+ return new PropertyFunction(key, function, computed);
+ } finally {
+ lc.pop(functionNode);
+ }
}
private static class PropertyFunction {
- final PropertyKey ident;
+ final Expression key;
final FunctionNode functionNode;
-
- PropertyFunction(final PropertyKey ident, final FunctionNode function) {
- this.ident = ident;
+ final boolean computed;
+
+ PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
+ this.key = key;
this.functionNode = function;
+ this.computed = computed;
}
}
/**
- * Parse left hand side expression.
- *
* LeftHandSideExpression :
* NewExpression
* CallExpression
*
* CallExpression :
* MemberExpression Arguments
+ * SuperCall
* CallExpression Arguments
* CallExpression [ Expression ]
* CallExpression . IdentifierName
- * CallExpression TemplateLiteral
+ *
+ * SuperCall :
+ * super Arguments
*
+ * See 11.2
+ *
+ * Parse left hand side expression.
* @return Expression node.
*/
private Expression leftHandSideExpression() {
@@ -2435,7 +3368,7 @@
lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
}
-loop:
+ loop:
while (true) {
// Capture token.
callLine = line;
@@ -2479,6 +3412,7 @@
// tagged template literal
final List<Expression> arguments = templateLiteralArgumentList();
+ // Create call node.
lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
break;
@@ -2506,6 +3440,20 @@
// NEW is tested in caller.
next();
+ if (type == PERIOD && isES6()) {
+ next();
+ if (type == IDENT && "target".equals(getValue())) {
+ if (lc.getCurrentFunction().isProgram()) {
+ throw error(AbstractParser.message("new.target.in.function"), token);
+ }
+ next();
+ markNewTarget(lc);
+ return new IdentNode(newToken, finish, "new.target");
+ } else {
+ throw error(AbstractParser.message("expected.target"), token);
+ }
+ }
+
// Get function base.
final int callLine = line;
final Expression constructor = memberExpression();
@@ -2541,21 +3489,33 @@
}
/**
- * Parse member expression.
- *
* MemberExpression :
* PrimaryExpression
- * FunctionExpression
+ * FunctionExpression
+ * ClassExpression
+ * GeneratorExpression
* MemberExpression [ Expression ]
* MemberExpression . IdentifierName
* MemberExpression TemplateLiteral
+ * SuperProperty
+ * MetaProperty
* new MemberExpression Arguments
*
+ * SuperProperty :
+ * super [ Expression ]
+ * super . IdentifierName
+ *
+ * MetaProperty :
+ * NewTarget
+ *
+ * Parse member expression.
* @return Expression node.
*/
+ @SuppressWarnings("fallthrough")
private Expression memberExpression() {
// Prepare to build operation.
Expression lhs;
+ boolean isSuper = false;
switch (type) {
case NEW:
@@ -2568,13 +3528,53 @@
lhs = functionExpression(false, false);
break;
+ case CLASS:
+ if (isES6()) {
+ lhs = classExpression(false);
+ break;
+ } else {
+ // fall through
+ }
+
+ case SUPER:
+ if (isES6()) {
+ final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
+ if (currentFunction.isMethod()) {
+ long identToken = Token.recast(token, IDENT);
+ next();
+ lhs = createIdentNode(identToken, finish, SUPER.getName());
+
+ switch (type) {
+ case LBRACKET:
+ case PERIOD:
+ getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
+ isSuper = true;
+ break;
+ case LPAREN:
+ if (currentFunction.isSubclassConstructor()) {
+ lhs = ((IdentNode)lhs).setIsDirectSuper();
+ break;
+ } else {
+ // fall through to throw error
+ }
+ default:
+ throw error(AbstractParser.message("invalid.super"), identToken);
+ }
+ break;
+ } else {
+ // fall through
+ }
+ } else {
+ // fall through
+ }
+
default:
// Get primary expression.
lhs = primaryExpression();
break;
}
-loop:
+ loop:
while (true) {
// Capture token.
final long callToken = token;
@@ -2591,6 +3591,11 @@
// Create indexing node.
lhs = new IndexNode(callToken, finish, lhs, index);
+ if (isSuper) {
+ isSuper = false;
+ lhs = ((BaseNode) lhs).setIsSuper();
+ }
+
break;
}
case PERIOD: {
@@ -2605,6 +3610,11 @@
// Create property access node.
lhs = new AccessNode(callToken, finish, lhs, property.getName());
+ if (isSuper) {
+ isSuper = false;
+ lhs = ((BaseNode) lhs).setIsSuper();
+ }
+
break;
}
case TEMPLATE:
@@ -2632,7 +3642,9 @@
*
* ArgumentList :
* AssignmentExpression
+ * ... AssignmentExpression
* ArgumentList , AssignmentExpression
+ * ArgumentList , ... AssignmentExpression
*
* See 11.2
*
@@ -2656,8 +3668,18 @@
first = false;
}
+ long spreadToken = 0;
+ if (type == ELLIPSIS && isES6()) {
+ spreadToken = token;
+ next();
+ }
+
// Get argument expression.
- nodeList.add(assignmentExpression(false));
+ Expression expression = assignmentExpression(false);
+ if (spreadToken != 0) {
+ expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
+ }
+ nodeList.add(expression);
}
expect(RPAREN);
@@ -2697,11 +3719,24 @@
final long functionToken = token;
final int functionLine = line;
// FUNCTION is tested in caller.
+ assert type == FUNCTION;
next();
+ boolean generator = false;
+ if (type == MUL && isES6()) {
+ generator = true;
+ next();
+ }
+
IdentNode name = null;
- if (type == IDENT || isNonStrictModeIdent()) {
+ if (isBindingIdentifier()) {
+ if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
+ // 12.1.1 Early SyntaxError if:
+ // GeneratorExpression with BindingIdentifier yield
+ // HoistableDeclaration with BindingIdentifier yield in generator function body
+ expect(IDENT);
+ }
name = getIdent();
verifyStrictIdent(name, "function name");
} else if (isStatement) {
@@ -2723,25 +3758,36 @@
isAnonymous = true;
}
- expect(LPAREN);
- final List<IdentNode> parameters = formalParameterList();
- expect(RPAREN);
-
- final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
+ FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
+ List<IdentNode> parameters = Collections.emptyList();
+ final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
lc.push(functionNode);
+
Block functionBody = null;
// Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
// If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
hideDefaultName();
- try{
+ try {
+ final ParserContextBlockNode parameterBlock = newBlock();
+ try {
+ expect(LPAREN);
+ parameters = formalParameterList(generator);
+ functionNode.setParameters(parameters);
+ expect(RPAREN);
+ } finally {
+ restoreBlock(parameterBlock);
+ }
+
functionBody = functionBody(functionNode);
+
+ functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
} finally {
defaultNames.pop();
lc.pop(functionNode);
}
if (isStatement) {
- if (topLevel || useBlockScope()) {
+ if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
functionNode.setFlag(FunctionNode.IS_DECLARED);
} else if (isStrictMode) {
throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
@@ -2759,45 +3805,14 @@
functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
}
- final int arity = parameters.size();
-
- final boolean strict = functionNode.isStrict();
- if (arity > 1) {
- final HashSet<String> parametersSet = new HashSet<>(arity);
-
- for (int i = arity - 1; i >= 0; i--) {
- final IdentNode parameter = parameters.get(i);
- String parameterName = parameter.getName();
-
- if (isArguments(parameterName)) {
- functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
- }
-
- if (parametersSet.contains(parameterName)) {
- // redefinition of parameter name
- if (strict) {
- throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
- }
- // rename in non-strict mode
- parameterName = functionNode.uniqueName(parameterName);
- final long parameterToken = parameter.getToken();
- parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
- }
-
- parametersSet.add(parameterName);
- }
- } else if (arity == 1) {
- if (isArguments(parameters.get(0))) {
- functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
- }
- }
+ verifyParameterList(parameters, functionNode);
final FunctionNode function = createFunctionNode(
functionNode,
functionToken,
name,
parameters,
- FunctionNode.Kind.NORMAL,
+ functionKind,
functionLine,
functionBody);
@@ -2822,6 +3837,40 @@
return function;
}
+ private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
+ final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
+ if (duplicateParameter != null) {
+ if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
+ throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
+ }
+
+ final int arity = parameters.size();
+ final HashSet<String> parametersSet = new HashSet<>(arity);
+
+ for (int i = arity - 1; i >= 0; i--) {
+ final IdentNode parameter = parameters.get(i);
+ String parameterName = parameter.getName();
+
+ if (parametersSet.contains(parameterName)) {
+ // redefinition of parameter name, rename in non-strict mode
+ parameterName = functionNode.uniqueName(parameterName);
+ final long parameterToken = parameter.getToken();
+ parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
+ }
+ parametersSet.add(parameterName);
+ }
+ }
+ }
+
+ private static Block maybeWrapBodyInParameterBlock(Block functionBody, ParserContextBlockNode parameterBlock) {
+ assert functionBody.isFunctionBody();
+ if (!parameterBlock.getStatements().isEmpty()) {
+ parameterBlock.appendStatement(new BlockStatement(functionBody));
+ return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
+ }
+ return functionBody;
+ }
+
private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
final String defaultFunctionName = getDefaultFunctionName();
if (isValidIdentifier(defaultFunctionName)) {
@@ -2836,14 +3885,14 @@
}
private static boolean isValidIdentifier(final String name) {
- if(name == null || name.isEmpty()) {
+ if (name == null || name.isEmpty()) {
return false;
}
- if(!Character.isJavaIdentifierStart(name.charAt(0))) {
+ if (!Character.isJavaIdentifierStart(name.charAt(0))) {
return false;
}
- for(int i = 1; i < name.length(); ++i) {
- if(!Character.isJavaIdentifierPart(name.charAt(i))) {
+ for (int i = 1; i < name.length(); ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
return false;
}
}
@@ -2851,12 +3900,12 @@
}
private String getDefaultFunctionName() {
- if(!defaultNames.isEmpty()) {
+ if (!defaultNames.isEmpty()) {
final Object nameExpr = defaultNames.peek();
- if(nameExpr instanceof PropertyKey) {
+ if (nameExpr instanceof PropertyKey) {
markDefaultNameUsed();
return ((PropertyKey)nameExpr).getPropertyName();
- } else if(nameExpr instanceof AccessNode) {
+ } else if (nameExpr instanceof AccessNode) {
markDefaultNameUsed();
return ((AccessNode)nameExpr).getProperty();
}
@@ -2885,8 +3934,8 @@
* Parse function parameter list.
* @return List of parameter nodes.
*/
- private List<IdentNode> formalParameterList() {
- return formalParameterList(RPAREN);
+ private List<IdentNode> formalParameterList(final boolean yield) {
+ return formalParameterList(RPAREN, yield);
}
/**
@@ -2902,7 +3951,7 @@
* Parse function parameter list.
* @return List of parameter nodes.
*/
- private List<IdentNode> formalParameterList(final TokenType endType) {
+ private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
// Prepare to gather parameters.
final ArrayList<IdentNode> parameters = new ArrayList<>();
// Track commas.
@@ -2916,12 +3965,84 @@
first = false;
}
- // Get and add parameter.
- final IdentNode ident = getIdent();
-
- // ECMA 13.1 strict mode restrictions
- verifyStrictIdent(ident, "function parameter");
-
+ boolean restParameter = false;
+ if (type == ELLIPSIS && isES6()) {
+ next();
+ restParameter = true;
+ }
+
+ if (type == YIELD && yield) {
+ expect(IDENT);
+ }
+
+ final long paramToken = token;
+ final int paramLine = line;
+ final String contextString = "function parameter";
+ IdentNode ident;
+ if (isBindingIdentifier() || restParameter || !isES6()) {
+ ident = bindingIdentifier(contextString);
+
+ if (restParameter) {
+ ident = ident.setIsRestParameter();
+ // rest parameter must be last
+ expectDontAdvance(endType);
+ parameters.add(ident);
+ break;
+ } else if (type == ASSIGN && isES6()) {
+ next();
+ ident = ident.setIsDefaultParameter();
+
+ if (type == YIELD && yield) {
+ // error: yield in default expression
+ expect(IDENT);
+ }
+
+ // default parameter
+ Expression initializer = assignmentExpression(false);
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ // desugar to: param = (param === undefined) ? initializer : param;
+ // possible alternative: if (param === undefined) param = initializer;
+ BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+ TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+ BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
+ lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+ }
+ }
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ currentFunction.addParameterBinding(ident);
+ if (ident.isRestParameter() || ident.isDefaultParameter()) {
+ currentFunction.setSimpleParameterList(false);
+ }
+ }
+ } else {
+ final Expression pattern = bindingPattern();
+ // Introduce synthetic temporary parameter to capture the object to be destructured.
+ ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
+ verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
+
+ Expression value = ident;
+ if (type == ASSIGN) {
+ next();
+ ident = ident.setIsDefaultParameter();
+
+ // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
+ Expression initializer = assignmentExpression(false);
+ // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
+ BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+ value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+ }
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ // destructuring assignment
+ BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
+ lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+ }
+ }
parameters.add(ident);
}
@@ -2929,6 +4050,23 @@
return parameters;
}
+ private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
+ verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
+ public void accept(IdentNode identNode) {
+ verifyIdent(identNode, contextString);
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ // declare function-scope variables for destructuring bindings
+ lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
+ // detect duplicate bounds names in parameter list
+ currentFunction.addParameterBinding(identNode);
+ currentFunction.setSimpleParameterList(false);
+ }
+ }
+ });
+ }
+
/**
* FunctionBody :
* SourceElements?
@@ -2958,7 +4096,7 @@
final int functionId = functionNode.getId();
parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
// Nashorn extension: expression closures
- if (!env._no_syntax_extensions && type != LBRACE) {
+ if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
/*
* Example:
*
@@ -2967,7 +4105,7 @@
*/
// just expression as function body
- final Expression expr = assignmentExpression(true);
+ final Expression expr = assignmentExpression(false);
lastToken = previousToken;
functionNode.setLastToken(previousToken);
assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
@@ -2982,6 +4120,7 @@
final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
appendStatement(returnNode);
}
+ // bodyFinish = finish;
} else {
expectDontAdvance(LBRACE);
if (parseBody || !skipFunctionBody(functionNode)) {
@@ -3054,7 +4193,7 @@
}
}
}
- functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
+ functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
return functionBody;
}
@@ -3095,8 +4234,7 @@
// Doesn't really matter, but it's safe to treat it as if there were a semicolon before
// the RBRACE.
type = SEMICOLON;
- k = -1;
- next();
+ scanFirstToken();
return true;
}
@@ -3126,11 +4264,11 @@
}
private void printAST(final FunctionNode functionNode) {
- if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
+ if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
env.getErr().println(new ASTWriter(functionNode));
}
- if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+ if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
env.getErr().println(new PrintVisitor(functionNode, true, false));
}
}
@@ -3222,20 +4360,7 @@
throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
}
- if (!(lhs instanceof AccessNode ||
- lhs instanceof IndexNode ||
- lhs instanceof IdentNode)) {
- return referenceError(lhs, null, env._early_lvalue_error);
- }
-
- if (lhs instanceof IdentNode) {
- if (!checkIdentLValue((IdentNode)lhs)) {
- return referenceError(lhs, null, false);
- }
- verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
- }
-
- return incDecExpression(unaryToken, opType, lhs, false);
+ return verifyIncDecExpression(unaryToken, opType, lhs, false);
default:
break;
@@ -3247,29 +4372,16 @@
switch (type) {
case INCPREFIX:
case DECPREFIX:
+ final long opToken = token;
final TokenType opType = type;
final Expression lhs = expression;
// ++, -- without operand..
if (lhs == null) {
throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
}
-
- if (!(lhs instanceof AccessNode ||
- lhs instanceof IndexNode ||
- lhs instanceof IdentNode)) {
- next();
- return referenceError(lhs, null, env._early_lvalue_error);
- }
- if (lhs instanceof IdentNode) {
- if (!checkIdentLValue((IdentNode)lhs)) {
- next();
- return referenceError(lhs, null, false);
- }
- verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
- }
- expression = incDecExpression(token, type, expression, true);
next();
- break;
+
+ return verifyIncDecExpression(opToken, opType, lhs, true);
default:
break;
}
@@ -3282,6 +4394,25 @@
return expression;
}
+ private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
+ assert lhs != null;
+
+ if (!(lhs instanceof AccessNode ||
+ lhs instanceof IndexNode ||
+ lhs instanceof IdentNode)) {
+ return referenceError(lhs, null, env._early_lvalue_error);
+ }
+
+ if (lhs instanceof IdentNode) {
+ if (!checkIdentLValue((IdentNode)lhs)) {
+ return referenceError(lhs, null, false);
+ }
+ verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
+ }
+
+ return incDecExpression(unaryToken, opType, lhs, isPostfix);
+ }
+
/**
* {@code
* MultiplicativeExpression :
@@ -3380,7 +4511,42 @@
// at expression start point!
// Include commas in expression parsing.
- return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
+ return expression(false);
+ }
+
+ private Expression expression(final boolean noIn) {
+ Expression assignmentExpression = assignmentExpression(noIn);
+ while (type == COMMARIGHT) {
+ long commaToken = token;
+ next();
+
+ boolean rhsRestParameter = false;
+ if (type == ELLIPSIS && isES6()) {
+ // (a, b, ...rest) is not a valid expression, unless we're parsing the parameter list of an arrow function (we need to throw the right error).
+ // But since the rest parameter is always last, at least we know that the expression has to end here and be followed by RPAREN and ARROW, so peek ahead.
+ if (isRestParameterEndOfArrowFunctionParameterList()) {
+ next();
+ rhsRestParameter = true;
+ }
+ }
+
+ Expression rhs = assignmentExpression(noIn);
+
+ if (rhsRestParameter) {
+ rhs = ((IdentNode)rhs).setIsRestParameter();
+ // Our only valid move is to end Expression here and continue with ArrowFunction.
+ // We've already checked that this is the parameter list of an arrow function (see above).
+ // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
+ assert type == RPAREN;
+ }
+
+ assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
+ }
+ return assignmentExpression;
+ }
+
+ private Expression expression(final int minPrecedence, final boolean noIn) {
+ return expression(unaryExpression(), minPrecedence, noIn);
}
private JoinPredecessorExpression joinPredecessorExpression() {
@@ -3448,12 +4614,316 @@
return lhs;
}
+ /**
+ * AssignmentExpression.
+ *
+ * AssignmentExpression[In, Yield] :
+ * ConditionalExpression[?In, ?Yield]
+ * [+Yield] YieldExpression[?In]
+ * ArrowFunction[?In, ?Yield]
+ * LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
+ * LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
+ */
protected Expression assignmentExpression(final boolean noIn) {
// This method is protected so that subclass can get details
// at assignment expression start point!
- // Exclude commas in expression parsing.
- return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
+ if (type == YIELD && inGeneratorFunction() && isES6()) {
+ return yieldExpression(noIn);
+ }
+
+ final long startToken = token;
+ final int startLine = line;
+ final Expression exprLhs = conditionalExpression(noIn);
+
+ if (type == ARROW && isES6()) {
+ if (checkNoLineTerminator()) {
+ final Expression paramListExpr;
+ if (exprLhs instanceof ExpressionList) {
+ paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
+ } else {
+ paramListExpr = exprLhs;
+ }
+ return arrowFunction(startToken, startLine, paramListExpr);
+ }
+ }
+ assert !(exprLhs instanceof ExpressionList);
+
+ if (isAssignmentOperator(type)) {
+ final boolean isAssign = type == ASSIGN;
+ if (isAssign) {
+ defaultNames.push(exprLhs);
+ }
+ try {
+ final long assignToken = token;
+ next();
+ final Expression exprRhs = assignmentExpression(noIn);
+ return verifyAssignment(assignToken, exprLhs, exprRhs);
+ } finally {
+ if (isAssign) {
+ defaultNames.pop();
+ }
+ }
+ } else {
+ return exprLhs;
+ }
+ }
+
+ /**
+ * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
+ */
+ private static boolean isAssignmentOperator(TokenType type) {
+ switch (type) {
+ case ASSIGN:
+ case ASSIGN_ADD:
+ case ASSIGN_BIT_AND:
+ case ASSIGN_BIT_OR:
+ case ASSIGN_BIT_XOR:
+ case ASSIGN_DIV:
+ case ASSIGN_MOD:
+ case ASSIGN_MUL:
+ case ASSIGN_SAR:
+ case ASSIGN_SHL:
+ case ASSIGN_SHR:
+ case ASSIGN_SUB:
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * ConditionalExpression.
+ */
+ private Expression conditionalExpression(boolean noIn) {
+ return expression(TERNARY.getPrecedence(), noIn);
+ }
+
+ /**
+ * ArrowFunction.
+ *
+ * @param startToken start token of the ArrowParameters expression
+ * @param functionLine start line of the arrow function
+ * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
+ */
+ private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
+ // caller needs to check that there's no LineTerminator between parameter list and arrow
+ assert type != ARROW || checkNoLineTerminator();
+ expect(ARROW);
+
+ final long functionToken = Token.recast(startToken, ARROW);
+ final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), "=>:" + functionLine);
+ final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
+ functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+
+ lc.push(functionNode);
+ try {
+ ParserContextBlockNode parameterBlock = newBlock();
+ final List<IdentNode> parameters;
+ try {
+ parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
+ functionNode.setParameters(parameters);
+
+ if (!functionNode.isSimpleParameterList()) {
+ markEvalInArrowParameterList(parameterBlock);
+ }
+ } finally {
+ restoreBlock(parameterBlock);
+ }
+ Block functionBody = functionBody(functionNode);
+
+ functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
+
+ verifyParameterList(parameters, functionNode);
+
+ final FunctionNode function = createFunctionNode(
+ functionNode,
+ functionToken,
+ name,
+ parameters,
+ FunctionNode.Kind.ARROW,
+ functionLine,
+ functionBody);
+ return function;
+ } finally {
+ lc.pop(functionNode);
+ }
+ }
+
+ private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
+ final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+ final ParserContextFunctionNode current = iter.next();
+ final ParserContextFunctionNode parent = iter.next();
+
+ if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
+ // we might have flagged has-eval in the parent function during parsing the parameter list,
+ // if the parameter list contains eval; must tag arrow function as has-eval.
+ for (final Statement st : parameterBlock.getStatements()) {
+ st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterCallNode(final CallNode callNode) {
+ if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
+ current.setFlag(FunctionNode.HAS_EVAL);
+ }
+ return true;
+ }
+ });
+ }
+ // TODO: function containing the arrow function should not be flagged has-eval
+ }
+ }
+
+ private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
+ final List<IdentNode> parameters;
+ if (paramListExpr == null) {
+ // empty parameter list, i.e. () =>
+ parameters = Collections.emptyList();
+ } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
+ parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
+ } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
+ parameters = new ArrayList<>();
+ Expression car = paramListExpr;
+ do {
+ final Expression cdr = ((BinaryNode) car).rhs();
+ parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
+ car = ((BinaryNode) car).lhs();
+ } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
+ parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
+ } else {
+ throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
+ }
+ return parameters;
+ }
+
+ private IdentNode verifyArrowParameter(Expression param, int index, int paramLine) {
+ final String contextString = "function parameter";
+ if (param instanceof IdentNode) {
+ IdentNode ident = (IdentNode)param;
+ verifyStrictIdent(ident, contextString);
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ currentFunction.addParameterBinding(ident);
+ }
+ return ident;
+ }
+
+ if (param.isTokenType(ASSIGN)) {
+ Expression lhs = ((BinaryNode) param).lhs();
+ long paramToken = lhs.getToken();
+ Expression initializer = ((BinaryNode) param).rhs();
+ if (lhs instanceof IdentNode) {
+ // default parameter
+ IdentNode ident = (IdentNode) lhs;
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+ TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+ BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
+ lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+
+ currentFunction.addParameterBinding(ident);
+ currentFunction.setSimpleParameterList(false);
+ }
+ return ident;
+ } else if (isDestructuringLhs(lhs)) {
+ // binding pattern with initializer
+ // Introduce synthetic temporary parameter to capture the object to be destructured.
+ IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
+ verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+ TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+ BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
+ lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+ }
+ return ident;
+ }
+ } else if (isDestructuringLhs(param)) {
+ // binding pattern
+ long paramToken = param.getToken();
+
+ // Introduce synthetic temporary parameter to capture the object to be destructured.
+ IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
+ verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
+
+ ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+ if (currentFunction != null) {
+ BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
+ lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+ }
+ return ident;
+ }
+ throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
+ }
+
+ private boolean checkNoLineTerminator() {
+ assert type == ARROW;
+ if (last == RPAREN) {
+ return true;
+ } else if (last == IDENT) {
+ return true;
+ }
+ for (int i = k - 1; i >= 0; i--) {
+ TokenType t = T(i);
+ switch (t) {
+ case RPAREN:
+ case IDENT:
+ return true;
+ case EOL:
+ return false;
+ case COMMENT:
+ continue;
+ default:
+ if (t.getKind() == TokenKind.FUTURESTRICT) {
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Peek ahead to see if what follows after the ellipsis is a rest parameter
+ * at the end of an arrow function parameter list.
+ */
+ private boolean isRestParameterEndOfArrowFunctionParameterList() {
+ assert type == ELLIPSIS;
+ // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
+ int i = 1;
+ for (;;) {
+ TokenType t = T(k + i++);
+ if (t == IDENT) {
+ break;
+ } else if (t == EOL || t == COMMENT) {
+ continue;
+ } else {
+ return false;
+ }
+ }
+ for (;;) {
+ TokenType t = T(k + i++);
+ if (t == RPAREN) {
+ break;
+ } else if (t == EOL || t == COMMENT) {
+ continue;
+ } else {
+ return false;
+ }
+ }
+ for (;;) {
+ TokenType t = T(k + i++);
+ if (t == ARROW) {
+ break;
+ } else if (t == COMMENT) {
+ continue;
+ } else {
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -3551,6 +5021,380 @@
cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
}
+
+ /**
+ * Parse a module.
+ *
+ * Module :
+ * ModuleBody?
+ *
+ * ModuleBody :
+ * ModuleItemList
+ */
+ private FunctionNode module(final String moduleName) {
+ boolean oldStrictMode = isStrictMode;
+ try {
+ isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
+
+ // Make a pseudo-token for the script holding its start and length.
+ int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
+ final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
+ final int functionLine = line;
+
+ final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
+ final ParserContextFunctionNode script = createParserContextFunctionNode(
+ ident,
+ functionToken,
+ FunctionNode.Kind.MODULE,
+ functionLine,
+ Collections.<IdentNode>emptyList());
+ lc.push(script);
+
+ final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
+ lc.push(module);
+
+ final ParserContextBlockNode body = newBlock();
+
+ functionDeclarations = new ArrayList<>();
+ moduleBody();
+ addFunctionDeclarations(script);
+ functionDeclarations = null;
+
+ restoreBlock(body);
+ body.setFlag(Block.NEEDS_SCOPE);
+ final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
+ lc.pop(module);
+ lc.pop(script);
+ script.setLastToken(token);
+
+ expect(EOF);
+
+ script.setModule(module.createModule());
+ return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
+ } finally {
+ isStrictMode = oldStrictMode;
+ }
+ }
+
+ /**
+ * Parse module body.
+ *
+ * ModuleBody :
+ * ModuleItemList
+ *
+ * ModuleItemList :
+ * ModuleItem
+ * ModuleItemList ModuleItem
+ *
+ * ModuleItem :
+ * ImportDeclaration
+ * ExportDeclaration
+ * StatementListItem
+ */
+ private void moduleBody() {
+ loop:
+ while (type != EOF) {
+ switch (type) {
+ case EOF:
+ break loop;
+ case IMPORT:
+ importDeclaration();
+ break;
+ case EXPORT:
+ exportDeclaration();
+ break;
+ default:
+ // StatementListItem
+ statement(true, false, false, false);
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Parse import declaration.
+ *
+ * ImportDeclaration :
+ * import ImportClause FromClause ;
+ * import ModuleSpecifier ;
+ * ImportClause :
+ * ImportedDefaultBinding
+ * NameSpaceImport
+ * NamedImports
+ * ImportedDefaultBinding , NameSpaceImport
+ * ImportedDefaultBinding , NamedImports
+ * ImportedDefaultBinding :
+ * ImportedBinding
+ * ModuleSpecifier :
+ * StringLiteral
+ * ImportedBinding :
+ * BindingIdentifier
+ */
+ private void importDeclaration() {
+ expect(IMPORT);
+ final ParserContextModuleNode module = lc.getCurrentModule();
+ if (type == STRING || type == ESCSTRING) {
+ // import ModuleSpecifier ;
+ final String moduleSpecifier = (String) getValue();
+ next();
+ module.addModuleRequest(moduleSpecifier);
+ } else {
+ // import ImportClause FromClause ;
+ List<Module.ImportEntry> importEntries;
+ if (type == MUL) {
+ importEntries = Collections.singletonList(nameSpaceImport());
+ } else if (type == LBRACE) {
+ importEntries = namedImports();
+ } else if (isBindingIdentifier()) {
+ // ImportedDefaultBinding
+ final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
+ Module.ImportEntry defaultImport = Module.ImportEntry.importDefault(importedDefaultBinding.getName());
+
+ if (type == COMMARIGHT) {
+ next();
+ importEntries = new ArrayList<>();
+ if (type == MUL) {
+ importEntries.add(nameSpaceImport());
+ } else if (type == LBRACE) {
+ importEntries.addAll(namedImports());
+ } else {
+ throw error(AbstractParser.message("expected.named.import"));
+ }
+ } else {
+ importEntries = Collections.singletonList(defaultImport);
+ }
+ } else {
+ throw error(AbstractParser.message("expected.import"));
+ }
+
+ final String moduleSpecifier = fromClause();
+ module.addModuleRequest(moduleSpecifier);
+ for (int i = 0; i < importEntries.size(); i++) {
+ module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier));
+ }
+ }
+ expect(SEMICOLON);
+ }
+
+ /**
+ * NameSpaceImport :
+ * * as ImportedBinding
+ *
+ * @return imported binding identifier
+ */
+ private Module.ImportEntry nameSpaceImport() {
+ assert type == MUL;
+ next();
+ final long asToken = token;
+ final String as = (String) expectValue(IDENT);
+ if (!"as".equals(as)) {
+ throw error(AbstractParser.message("expected.as"), asToken);
+ }
+ final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
+ return Module.ImportEntry.importStarAsNameSpaceFrom(localNameSpace.getName());
+ }
+
+ /**
+ * NamedImports :
+ * { }
+ * { ImportsList }
+ * { ImportsList , }
+ * ImportsList :
+ * ImportSpecifier
+ * ImportsList , ImportSpecifier
+ * ImportSpecifier :
+ * ImportedBinding
+ * IdentifierName as ImportedBinding
+ * ImportedBinding :
+ * BindingIdentifier
+ */
+ private List<Module.ImportEntry> namedImports() {
+ assert type == LBRACE;
+ next();
+ List<Module.ImportEntry> importEntries = new ArrayList<>();
+ while (type != RBRACE) {
+ final boolean bindingIdentifier = isBindingIdentifier();
+ final long nameToken = token;
+ final IdentNode importName = getIdentifierName();
+ if (type == IDENT && "as".equals(getValue())) {
+ next();
+ final IdentNode localName = bindingIdentifier("ImportedBinding");
+ importEntries.add(Module.ImportEntry.importSpecifier(importName.getName(), localName.getName()));
+ } else if (!bindingIdentifier) {
+ throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
+ } else {
+ importEntries.add(Module.ImportEntry.importSpecifier(importName.getName()));
+ }
+ if (type == COMMARIGHT) {
+ next();
+ } else {
+ break;
+ }
+ }
+ expect(RBRACE);
+ return importEntries;
+ }
+
+ /**
+ * FromClause :
+ * from ModuleSpecifier
+ */
+ private String fromClause() {
+ final long fromToken = token;
+ final String name = (String) expectValue(IDENT);
+ if (!"from".equals(name)) {
+ throw error(AbstractParser.message("expected.from"), fromToken);
+ }
+ if (type == STRING || type == ESCSTRING) {
+ final String moduleSpecifier = (String) getValue();
+ next();
+ return moduleSpecifier;
+ } else {
+ throw error(expectMessage(STRING));
+ }
+ }
+
+ /**
+ * Parse export declaration.
+ *
+ * ExportDeclaration :
+ * export * FromClause ;
+ * export ExportClause FromClause ;
+ * export ExportClause ;
+ * export VariableStatement
+ * export Declaration
+ * export default HoistableDeclaration[Default]
+ * export default ClassDeclaration[Default]
+ * export default [lookahead !in {function, class}] AssignmentExpression[In] ;
+ */
+ private void exportDeclaration() {
+ expect(EXPORT);
+ final ParserContextModuleNode module = lc.getCurrentModule();
+ switch (type) {
+ case MUL: {
+ next();
+ final String moduleRequest = fromClause();
+ expect(SEMICOLON);
+ module.addModuleRequest(moduleRequest);
+ module.addStarExportEntry(Module.ExportEntry.exportStarFrom(moduleRequest));
+ break;
+ }
+ case LBRACE: {
+ final List<Module.ExportEntry> exportEntries = exportClause();
+ if (type == IDENT && "from".equals(getValue())) {
+ final String moduleRequest = fromClause();
+ module.addModuleRequest(moduleRequest);
+ for (Module.ExportEntry exportEntry : exportEntries) {
+ module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest));
+ }
+ } else {
+ for (Module.ExportEntry exportEntry : exportEntries) {
+ module.addLocalExportEntry(exportEntry);
+ }
+ }
+ expect(SEMICOLON);
+ break;
+ }
+ case DEFAULT:
+ next();
+ final Expression assignmentExpression;
+ IdentNode ident;
+ final int lineNumber = line;
+ final long rhsToken = token;
+ final boolean declaration;
+ switch (type) {
+ case FUNCTION:
+ assignmentExpression = functionExpression(false, true);
+ ident = ((FunctionNode) assignmentExpression).getIdent();
+ declaration = true;
+ break;
+ case CLASS:
+ assignmentExpression = classDeclaration(true);
+ ident = ((ClassNode) assignmentExpression).getIdent();
+ declaration = true;
+ break;
+ default:
+ assignmentExpression = assignmentExpression(false);
+ ident = null;
+ declaration = false;
+ break;
+ }
+ if (ident != null) {
+ module.addLocalExportEntry(Module.ExportEntry.exportDefault(ident.getName()));
+ } else {
+ ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
+ lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
+ if (!declaration) {
+ expect(SEMICOLON);
+ }
+ module.addLocalExportEntry(Module.ExportEntry.exportDefault());
+ }
+ break;
+ case VAR:
+ case LET:
+ case CONST:
+ final List<Statement> statements = lc.getCurrentBlock().getStatements();
+ final int previousEnd = statements.size();
+ variableStatement(type);
+ for (final Statement statement : statements.subList(previousEnd, statements.size())) {
+ if (statement instanceof VarNode) {
+ module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName().getName()));
+ }
+ }
+ break;
+ case CLASS: {
+ final ClassNode classDeclaration = classDeclaration(false);
+ module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent().getName()));
+ break;
+ }
+ case FUNCTION: {
+ final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
+ module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent().getName()));
+ break;
+ }
+ default:
+ throw error(AbstractParser.message("invalid.export"), token);
+ }
+ }
+
+ /**
+ * ExportClause :
+ * { }
+ * { ExportsList }
+ * { ExportsList , }
+ * ExportsList :
+ * ExportSpecifier
+ * ExportsList , ExportSpecifier
+ * ExportSpecifier :
+ * IdentifierName
+ * IdentifierName as IdentifierName
+ *
+ * @return a list of ExportSpecifiers
+ */
+ private List<Module.ExportEntry> exportClause() {
+ assert type == LBRACE;
+ next();
+ List<Module.ExportEntry> exports = new ArrayList<>();
+ while (type != RBRACE) {
+ final IdentNode localName = getIdentifierName();
+ if (type == IDENT && "as".equals(getValue())) {
+ next();
+ final IdentNode exportName = getIdentifierName();
+ exports.add(Module.ExportEntry.exportSpecifier(exportName.getName(), localName.getName()));
+ } else {
+ exports.add(Module.ExportEntry.exportSpecifier(localName.getName()));
+ }
+ if (type == COMMARIGHT) {
+ next();
+ } else {
+ break;
+ }
+ }
+ expect(RBRACE);
+ return exports;
+ }
+
@Override
public String toString() {
return "'JavaScript Parsing'";
@@ -3564,6 +5408,12 @@
if (!flaggedCurrentFn) {
fn.setFlag(FunctionNode.HAS_EVAL);
flaggedCurrentFn = true;
+ if (fn.getKind() == FunctionNode.Kind.ARROW) {
+ // possible use of this in an eval that's nested in an arrow function, e.g.:
+ // function fun(){ return (() => eval("this"))(); };
+ markThis(lc);
+ markNewTarget(lc);
+ }
} else {
fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
}
@@ -3583,4 +5433,55 @@
private void appendStatement(final Statement statement) {
lc.appendStatementToCurrentNode(statement);
}
+
+ private static void markSuperCall(final ParserContext lc) {
+ final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+ while (iter.hasNext()) {
+ final ParserContextFunctionNode fn = iter.next();
+ if (fn.getKind() != FunctionNode.Kind.ARROW) {
+ assert fn.isSubclassConstructor();
+ fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
+ break;
+ }
+ }
+ }
+
+ private ParserContextFunctionNode getCurrentNonArrowFunction() {
+ final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+ while (iter.hasNext()) {
+ final ParserContextFunctionNode fn = iter.next();
+ if (fn.getKind() != FunctionNode.Kind.ARROW) {
+ return fn;
+ }
+ }
+ return null;
+ }
+
+ private static void markThis(final ParserContext lc) {
+ final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+ while (iter.hasNext()) {
+ final ParserContextFunctionNode fn = iter.next();
+ fn.setFlag(FunctionNode.USES_THIS);
+ if (fn.getKind() != FunctionNode.Kind.ARROW) {
+ break;
+ }
+ }
+ }
+
+ private static void markNewTarget(final ParserContext lc) {
+ final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+ while (iter.hasNext()) {
+ final ParserContextFunctionNode fn = iter.next();
+ if (fn.getKind() != FunctionNode.Kind.ARROW) {
+ if (!fn.isProgram()) {
+ fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
+ }
+ break;
+ }
+ }
+ }
+
+ private boolean inGeneratorFunction() {
+ return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java Fri May 06 06:23:30 2016 -0700
@@ -278,7 +278,12 @@
return new NodeIterator<>(ParserContextFunctionNode.class);
}
- private class NodeIterator <T extends ParserContextNode> implements Iterator<T> {
+ public ParserContextModuleNode getCurrentModule() {
+ final Iterator<ParserContextModuleNode> iter = new NodeIterator<>(ParserContextModuleNode.class, getCurrentFunction());
+ return iter.hasNext() ? iter.next() : null;
+ }
+
+ private class NodeIterator<T extends ParserContextNode> implements Iterator<T> {
private int index;
private T next;
private final Class<T> clazz;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java Fri May 06 06:23:30 2016 -0700
@@ -24,10 +24,12 @@
*/
package jdk.nashorn.internal.parser;
+import java.util.HashSet;
import java.util.List;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.Module;
/**
* ParserContextNode that represents a function that is currently being parsed
@@ -46,11 +48,11 @@
/** Line number for function declaration */
private final int line;
- /** Function node kind, see {@link FunctionNode#Kind} */
+ /** Function node kind, see {@link FunctionNode.Kind} */
private final FunctionNode.Kind kind;
/** List of parameter identifiers for function */
- private final List<IdentNode> parameters;
+ private List<IdentNode> parameters;
/** Token for function start */
private final long token;
@@ -61,6 +63,14 @@
/** Opaque node for parser end state, see {@link Parser} */
private Object endParserState;
+ private HashSet<String> parameterBoundNames;
+ private IdentNode duplicateParameterBinding;
+ private boolean simpleParameterList = true;
+
+ private Module module;
+
+ private int debugFlags;
+
/**
* @param token The token for the function
* @param ident External function name
@@ -155,6 +165,10 @@
return parameters;
}
+ void setParameters(List<IdentNode> parameters) {
+ this.parameters = parameters;
+ }
+
/**
* Set last token
* @param token New last token
@@ -194,4 +208,70 @@
public int getId() {
return isProgram() ? -1 : Token.descPosition(token);
}
+
+ /**
+ * Returns the debug flags for this function.
+ *
+ * @return the debug flags
+ */
+ int getDebugFlags() {
+ return debugFlags;
+ }
+
+ /**
+ * Sets a debug flag for this function.
+ *
+ * @param debugFlag the debug flag
+ */
+ void setDebugFlag(final int debugFlag) {
+ debugFlags |= debugFlag;
+ }
+
+ public boolean isMethod() {
+ return getFlag(FunctionNode.ES6_IS_METHOD) != 0;
+ }
+
+ public boolean isClassConstructor() {
+ return getFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR) != 0;
+ }
+
+ public boolean isSubclassConstructor() {
+ return getFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR) != 0;
+ }
+
+ boolean addParameterBinding(final IdentNode bindingIdentifier) {
+ if (Parser.isArguments(bindingIdentifier)) {
+ setFlag(FunctionNode.DEFINES_ARGUMENTS);
+ }
+
+ if (parameterBoundNames == null) {
+ parameterBoundNames = new HashSet<>();
+ }
+ if (parameterBoundNames.add(bindingIdentifier.getName())) {
+ return true;
+ } else {
+ duplicateParameterBinding = bindingIdentifier;
+ return false;
+ }
+ }
+
+ public IdentNode getDuplicateParameterBinding() {
+ return duplicateParameterBinding;
+ }
+
+ public boolean isSimpleParameterList() {
+ return simpleParameterList;
+ }
+
+ public void setSimpleParameterList(final boolean simpleParameterList) {
+ this.simpleParameterList = simpleParameterList;
+ }
+
+ public Module getModule() {
+ return module;
+ }
+
+ public void setModule(final Module module) {
+ this.module = module;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,90 @@
+/*
+ * 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
+ * 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.nashorn.internal.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.nashorn.internal.ir.Module;
+import jdk.nashorn.internal.ir.Module.ExportEntry;
+import jdk.nashorn.internal.ir.Module.ImportEntry;
+
+/**
+ * ParserContextNode that represents a module.
+ */
+class ParserContextModuleNode extends ParserContextBaseNode {
+
+ /** Module name. */
+ private final String name;
+
+ private List<String> requestedModules = new ArrayList<>();
+ private List<ImportEntry> importEntries = new ArrayList<>();
+ private List<ExportEntry> localExportEntries = new ArrayList<>();
+ private List<ExportEntry> indirectExportEntries = new ArrayList<>();
+ private List<ExportEntry> starExportEntries = new ArrayList<>();
+
+ /**
+ * Constructor.
+ *
+ * @param name name of the module
+ */
+ ParserContextModuleNode(final String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of the module.
+ *
+ * @return name of the module
+ */
+ public String getModuleName() {
+ return name;
+ }
+
+ public void addModuleRequest(final String moduleRequest) {
+ requestedModules.add(moduleRequest);
+ }
+
+ public void addImportEntry(final ImportEntry importEntry) {
+ importEntries.add(importEntry);
+ }
+
+ public void addLocalExportEntry(final ExportEntry exportEntry) {
+ localExportEntries.add(exportEntry);
+ }
+
+ public void addIndirectExportEntry(final ExportEntry exportEntry) {
+ indirectExportEntries.add(exportEntry);
+ }
+
+ public void addStarExportEntry(final ExportEntry exportEntry) {
+ starExportEntries.add(exportEntry);
+ }
+
+ public Module createModule() {
+ return new Module(requestedModules, importEntries, localExportEntries, indirectExportEntries, starExportEntries);
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Fri May 06 06:23:30 2016 -0700
@@ -82,7 +82,7 @@
ASSIGN (BINARY, "=", 2, false),
EQ (BINARY, "==", 9, true),
EQ_STRICT (BINARY, "===", 9, true),
- BIND (BINARY, "=>", 9, true),
+ ARROW (BINARY, "=>", 2, true),
GT (BINARY, ">", 10, true),
GE (BINARY, ">=", 10, true),
SAR (BINARY, ">>", 11, true),
@@ -100,6 +100,7 @@
OR (BINARY, "||", 4, true),
RBRACE (BRACKET, "}"),
BIT_NOT (UNARY, "~", 14, false),
+ ELLIPSIS (UNARY, "..."),
// ECMA 7.6.1.1 Keywords, 7.6.1.2 Future Reserved Words.
// All other Java keywords are commented out.
@@ -190,7 +191,10 @@
COMMALEFT (IR, null),
DECPOSTFIX (IR, null),
- INCPOSTFIX (IR, null);
+ INCPOSTFIX (IR, null),
+ SPREAD_ARGUMENT(IR, null),
+ SPREAD_ARRAY (IR, null),
+ YIELD_STAR (IR, null);
/** Next token kind in token lookup table. */
private TokenType next;
@@ -251,7 +255,6 @@
return kind == BINARY && (!noIn || this != IN) && precedence != 0;
}
-
public int getLength() {
assert name != null : "Token name not set";
return name.length();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Fri May 06 06:23:30 2016 -0700
@@ -1403,11 +1403,11 @@
return null;
}
- if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
+ if (env._print_ast || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
getErr().println(new ASTWriter(functionNode));
}
- if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+ if (env._print_parse || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
getErr().println(new PrintVisitor(functionNode, true, false));
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java Fri May 06 06:23:30 2016 -0700
@@ -176,6 +176,8 @@
buffer.append('0');
}
buffer.append(chars, 0, length);
+ } else {
+ decimalPoint = 1;
}
} else if (decimalPoint >= length) {
// large integer, add trailing zeroes
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Fri May 06 06:23:30 2016 -0700
@@ -63,6 +63,27 @@
parser.error.missing.const.assignment=Missing assignment to constant "{0}"
parser.error.unterminated.template.expression=Expected } after expression in template literal
+# ES6 mode error messages
+parser.error.multiple.constructors=Class contains more than one constructor
+parser.error.generator.constructor=Class constructor must not be a generator
+parser.error.accessor.constructor=Class constructor must not be an accessor
+parser.error.static.prototype.method=Static class method must not be named 'prototype'
+parser.error.missing.destructuring.assignment=Missing assignment in destructuring declaration
+parser.error.let.binding.for='let' is not a valid binding name in a for loop
+parser.error.invalid.export=invalid export declaration
+parser.error.expected.binding=expected BindingIdentifier or BindingPattern
+parser.error.multiple.proto.key=property name __proto__ appears more than once in object literal
+parser.error.new.target.in.function=new.target expression is only allowed in functions
+parser.error.expected.target=expected 'target'
+parser.error.invalid.super=invalid use of keyword super
+parser.error.expected.arrow.parameter=expected arrow function parameter list
+parser.error.invalid.arrow.parameter=invalid arrow function parameter
+parser.error.expected.named.import=expected NameSpaceImport or NamedImports
+parser.error.expected.import=expected ImportClause or ModuleSpecifier
+parser.error.expected.as=expected 'as'
+parser.error.expected.binding.identifier=expected BindingIdentifier
+parser.error.expected.from=expected 'from'
+
# strict mode error messages
parser.error.strict.no.with="with" statement cannot be used in strict mode
parser.error.strict.name="{0}" cannot be used as {1} in strict mode
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Fri May 06 06:23:30 2016 -0700
@@ -438,6 +438,9 @@
final File file = new File(fileName);
final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global);
if (script == null || errors.getNumberOfErrors() != 0) {
+ if (context.getEnv()._parse_only && !errors.hasErrors()) {
+ continue; // No error, continue to consume all files in list
+ }
return COMPILATION_ERROR;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8155025.js Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8155025: 0.001.toFixed(2) should return "0.00" not "0"
+ *
+ * @test
+ * @run
+ */
+
+for (var i = 0, zeros=""; i <= 9; i++, zeros += "0") {
+ var n = Number("0." + zeros + "1");
+ for (var j = 1; j <= i + 3; j++) {
+ print(n + ".toFixed(" + j + ")=" + n.toFixed(j));
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8155025.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,75 @@
+0.1.toFixed(1)=0.1
+0.1.toFixed(2)=0.10
+0.1.toFixed(3)=0.100
+0.01.toFixed(1)=0.0
+0.01.toFixed(2)=0.01
+0.01.toFixed(3)=0.010
+0.01.toFixed(4)=0.0100
+0.001.toFixed(1)=0.0
+0.001.toFixed(2)=0.00
+0.001.toFixed(3)=0.001
+0.001.toFixed(4)=0.0010
+0.001.toFixed(5)=0.00100
+0.0001.toFixed(1)=0.0
+0.0001.toFixed(2)=0.00
+0.0001.toFixed(3)=0.000
+0.0001.toFixed(4)=0.0001
+0.0001.toFixed(5)=0.00010
+0.0001.toFixed(6)=0.000100
+0.00001.toFixed(1)=0.0
+0.00001.toFixed(2)=0.00
+0.00001.toFixed(3)=0.000
+0.00001.toFixed(4)=0.0000
+0.00001.toFixed(5)=0.00001
+0.00001.toFixed(6)=0.000010
+0.00001.toFixed(7)=0.0000100
+0.000001.toFixed(1)=0.0
+0.000001.toFixed(2)=0.00
+0.000001.toFixed(3)=0.000
+0.000001.toFixed(4)=0.0000
+0.000001.toFixed(5)=0.00000
+0.000001.toFixed(6)=0.000001
+0.000001.toFixed(7)=0.0000010
+0.000001.toFixed(8)=0.00000100
+1e-7.toFixed(1)=0.0
+1e-7.toFixed(2)=0.00
+1e-7.toFixed(3)=0.000
+1e-7.toFixed(4)=0.0000
+1e-7.toFixed(5)=0.00000
+1e-7.toFixed(6)=0.000000
+1e-7.toFixed(7)=0.0000001
+1e-7.toFixed(8)=0.00000010
+1e-7.toFixed(9)=0.000000100
+1e-8.toFixed(1)=0.0
+1e-8.toFixed(2)=0.00
+1e-8.toFixed(3)=0.000
+1e-8.toFixed(4)=0.0000
+1e-8.toFixed(5)=0.00000
+1e-8.toFixed(6)=0.000000
+1e-8.toFixed(7)=0.0000000
+1e-8.toFixed(8)=0.00000001
+1e-8.toFixed(9)=0.000000010
+1e-8.toFixed(10)=0.0000000100
+1e-9.toFixed(1)=0.0
+1e-9.toFixed(2)=0.00
+1e-9.toFixed(3)=0.000
+1e-9.toFixed(4)=0.0000
+1e-9.toFixed(5)=0.00000
+1e-9.toFixed(6)=0.000000
+1e-9.toFixed(7)=0.0000000
+1e-9.toFixed(8)=0.00000000
+1e-9.toFixed(9)=0.000000001
+1e-9.toFixed(10)=0.0000000010
+1e-9.toFixed(11)=0.00000000100
+1e-10.toFixed(1)=0.0
+1e-10.toFixed(2)=0.00
+1e-10.toFixed(3)=0.000
+1e-10.toFixed(4)=0.0000
+1e-10.toFixed(5)=0.00000
+1e-10.toFixed(6)=0.000000
+1e-10.toFixed(7)=0.0000000
+1e-10.toFixed(8)=0.00000000
+1e-10.toFixed(9)=0.000000000
+1e-10.toFixed(10)=0.0000000001
+1e-10.toFixed(11)=0.00000000010
+1e-10.toFixed(12)=0.000000000100
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/parser-es6.js Fri May 06 06:23:30 2016 -0700
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8134503: support ES6 parsing in Nashorn
+ *
+ * @test
+ * @option --language=es6
+ * @option --parse-only
+ */
+
+
+[].map(v => v + 1);
+
+class A extends B.C {
+ constructor(a, b) {
+ super(a, b);
+ }
+ someMethod(c) {
+ super.someMethod();
+ }
+ get g() {
+ return this.g;
+ }
+ set s(t) {
+ this.t = t;
+ }
+ static m() {
+ return k;
+ }
+}
+
+var obj = {
+ __proto__: theProtoObj,
+ handler,
+ r() {
+ return super.m();
+ },
+ [ '__' + (() => 'x')() ]: 1,
+ *q (x, y) {
+ yield 1;
+ }
+};
+
+var [a, , b] = [1, 2, 3];
+
+var { x: a, y: { z: b }, w: c } = abc();
+
+var {a, b, c} = abc();
+
+var o = { x, y };
+
+function g({name: x}) {
+ return x;
+}
+
+foo(a, ...b);
+
+var c = [ ...s ];
+
+var [a] = [];
+
+var [a = 1] = [];
+
+
+var f = {
+ [Symbol.iterator]: function*() {
+ var cur = 1;
+ for (;;) {
+ yield cur;
+ }
+ }
+};
+
--- a/nashorn/test/script/basic/yield.js Fri May 06 11:47:45 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/**
- * Check yield keyword is parsed and yield statement does nothing (yet).
- *
- * @test
- * @run
- */
-
-function func() {
- yield 2;
-}
--- a/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -1,3 +1,3 @@
-test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:14 strict mode function cannot have duplicate parameter name "x"
+test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:17 strict mode function cannot have duplicate parameter name "x"
function func(x, x) {}
- ^
+ ^
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -100,7 +100,7 @@
"startPosition": "1181",
"properties": [
{
- "endPosition": "1185",
+ "endPosition": "1187",
"kind": "PROPERTY",
"value": {
"endPosition": "1187",
@@ -2386,7 +2386,7 @@
"startPosition": "1139",
"properties": [
{
- "endPosition": "1143",
+ "endPosition": "1146",
"kind": "PROPERTY",
"value": {
"endPosition": "1146",
@@ -2403,7 +2403,7 @@
}
},
{
- "endPosition": "1150",
+ "endPosition": "1152",
"kind": "PROPERTY",
"value": {
"endPosition": "1152",
@@ -2443,7 +2443,7 @@
"startPosition": "1160",
"properties": [
{
- "endPosition": "1166",
+ "endPosition": "1169",
"kind": "PROPERTY",
"value": {
"endPosition": "1169",
@@ -2460,7 +2460,7 @@
}
},
{
- "endPosition": "1175",
+ "endPosition": "1177",
"kind": "PROPERTY",
"value": {
"endPosition": "1177",
@@ -2914,7 +2914,7 @@
"startPosition": "1178",
"properties": [
{
- "endPosition": "1182",
+ "endPosition": "1184",
"kind": "PROPERTY",
"value": {
"endPosition": "1184",
@@ -3395,7 +3395,7 @@
"startPosition": "1200",
"properties": [
{
- "endPosition": "1206",
+ "endPosition": "1214",
"kind": "PROPERTY",
"value": {
"endPosition": "1214",
@@ -4709,11 +4709,11 @@
,
{
"fileName": "parsernegativetests/strict_repeatparam.js",
- "code": "ident (1119, 1)",
- "columnNumber": "14",
+ "code": "ident (1122, 1)",
+ "columnNumber": "17",
"kind": "ERROR",
- "position": "1119",
- "message": "parsernegativetests/strict_repeatparam.js:31:14 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^",
+ "position": "1122",
+ "message": "parsernegativetests/strict_repeatparam.js:31:17 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^",
"lineNumber": "31"
}
,
--- a/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -6,10 +6,10 @@
with({}) {}
^
-repeat_param.js:2:15 strict mode function cannot have duplicate parameter name "x"
+repeat_param.js:2:18 strict mode function cannot have duplicate parameter name "x"
function func(x, x) {}
- ^
+ ^
repeat_prop.js:2:22 Property "foo" already defined
var obj = { foo: 34, foo: 'hello' };
--- a/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -74,7 +74,7 @@
"properties": [
{
"getter": "null",
- "endPosition": "74",
+ "endPosition": "76",
"kind": "PROPERTY",
"setter": "null",
"value": {
--- a/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -6,7 +6,7 @@
"properties": [
{
"getter": "null",
- "endPosition": "8",
+ "endPosition": "12",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -38,7 +38,7 @@
"properties": [
{
"getter": "null",
- "endPosition": "34",
+ "endPosition": "37",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -57,7 +57,7 @@
},
{
"getter": "null",
- "endPosition": "41",
+ "endPosition": "43",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -83,7 +83,7 @@
"properties": [
{
"getter": "null",
- "endPosition": "57",
+ "endPosition": "60",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -102,7 +102,7 @@
},
{
"getter": "null",
- "endPosition": "66",
+ "endPosition": "68",
"kind": "PROPERTY",
"setter": "null",
"value": {
--- a/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -1,7 +1,7 @@
[
{
"getter": "null",
- "endPosition": "17",
+ "endPosition": "22",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -20,7 +20,7 @@
},
{
"getter": "null",
- "endPosition": "31",
+ "endPosition": "38",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -45,7 +45,7 @@
},
{
"getter": "null",
- "endPosition": "46",
+ "endPosition": "61",
"kind": "PROPERTY",
"setter": "null",
"value": {
@@ -72,7 +72,7 @@
},
{
"getter": "null",
- "endPosition": "69",
+ "endPosition": "72",
"kind": "PROPERTY",
"setter": "null",
"value": {
--- a/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -80,7 +80,7 @@
"properties": [
{
"getter": "null",
- "endPosition": "97",
+ "endPosition": "105",
"kind": "PROPERTY",
"setter": "null",
"value": {
--- a/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED Fri May 06 06:23:30 2016 -0700
@@ -49,7 +49,7 @@
"properties": [
{
"getter": "null",
- "endPosition": "34",
+ "endPosition": "39",
"kind": "PROPERTY",
"setter": "null",
"value": {
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java Fri May 06 11:47:45 2016 +0300
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java Fri May 06 06:23:30 2016 -0700
@@ -194,9 +194,9 @@
pb.redirectError(errorFileHandle);
final Process process = pb.start();
- process.waitFor();
+ final int exitCode = process.waitFor();
- if (errorFileHandle.length() > 0) {
+ if (exitCode != 0 || errorFileHandle.length() > 0) {
if (expectRunFailure) {
return;
}