From fe9e5e1b5e911c7d7531cfe51739b07862820c6f Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 24 Mar 2017 09:16:58 -0700 Subject: [PATCH 01/14] 8177550: (fc) Enable java/nio/channels/FileChannel/{Transfer4GBFile.java,TransferTo6GBFile.java} on Linux and Windows Re-enabled tests currently suppressed on Linux and Windows as the timeouts have been increased. Reviewed-by: alanb --- jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java | 5 ----- .../java/nio/channels/FileChannel/TransferTo6GBFile.java | 5 ----- 2 files changed, 10 deletions(-) diff --git a/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java b/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java index 7aa87d7de42..22240e767bf 100644 --- a/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java +++ b/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java @@ -52,11 +52,6 @@ public class Transfer4GBFile { // Test transferTo with large file @Test public void xferTest04() throws Exception { // for bug 4638365 - // Windows and Linux can't handle the really large file sizes for a - // truncate or a positional write required by the test for 4563125 - String osName = System.getProperty("os.name"); - if (!(osName.startsWith("SunOS") || osName.contains("OS X"))) - return; File source = File.createTempFile("blah", null); source.deleteOnExit(); long testSize = ((long)Integer.MAX_VALUE) * 2; diff --git a/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java b/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java index bdc44e2416d..2365351e85a 100644 --- a/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java +++ b/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java @@ -50,11 +50,6 @@ public class TransferTo6GBFile { // Test transferTo with file positions larger than 2 and 4GB @Test public void xferTest08() throws Exception { // for bug 6253145 - // Creating a sparse 6GB file on Windows takes too long - String osName = System.getProperty("os.name"); - if (osName.startsWith("Windows")) - return; - final long G = 1024L * 1024L * 1024L; // Create 6GB file From 2823ea6a653def5362990a64e8531040068ccb27 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 24 Mar 2017 16:35:51 +0000 Subject: [PATCH 02/14] 8177474: Do not emit warnings when illegal access is allowed by --add-exports/--add-opens Reviewed-by: chegar, mchung --- .../internal/module/IllegalAccessLogger.java | 65 ++++++++++----- .../jdk/internal/module/ModuleBootstrap.java | 18 ++--- .../classes/sun/launcher/LauncherHelper.java | 27 +------ .../launcher/resources/launcher.properties | 2 - .../modules/permit/PermitIllegalAccess.java | 79 ++++++++++++++++--- 5 files changed, 124 insertions(+), 67 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java index 23e3ed2a7a0..a502cd0c762 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java @@ -25,6 +25,7 @@ package jdk.internal.module; +import java.io.PrintStream; import java.lang.invoke.MethodHandles; import java.lang.reflect.Module; import java.net.URL; @@ -42,6 +43,9 @@ import java.util.WeakHashMap; import java.util.function.Supplier; import java.util.stream.Collectors; +import jdk.internal.loader.BootLoader; +import sun.security.action.GetPropertyAction; + /** * Supports logging of access to members of API packages that are exported or * opened via backdoor mechanisms to code in unnamed modules. @@ -49,15 +53,24 @@ import java.util.stream.Collectors; public final class IllegalAccessLogger { - // true to print stack trace - private static final boolean PRINT_STACK_TRACE; - static { - String s = System.getProperty("sun.reflect.debugModuleAccessChecks"); - PRINT_STACK_TRACE = "access".equals(s); - } + /** + * Holder class to lazily create the StackWalker object and determine + * if the stack trace should be printed + */ + static class Holder { + static final StackWalker STACK_WALKER; + static final boolean PRINT_STACK_TRACE; - private static final StackWalker STACK_WALKER - = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + static { + PrivilegedAction pa = () -> + StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + STACK_WALKER = AccessController.doPrivileged(pa); + + String name = "sun.reflect.debugModuleAccessChecks"; + String value = GetPropertyAction.privilegedGetProperty(name, null); + PRINT_STACK_TRACE = "access" .equals(value); + } + } // the maximum number of frames to capture private static final int MAX_STACK_FRAMES = 32; @@ -72,10 +85,15 @@ public final class IllegalAccessLogger { private final Map> exported; private final Map> opened; + // the print stream to send the warnings + private final PrintStream warningStream; + private IllegalAccessLogger(Map> exported, - Map> opened) { + Map> opened, + PrintStream warningStream) { this.exported = deepCopy(exported); this.opened = deepCopy(opened); + this.warningStream = warningStream; } /** @@ -168,7 +186,7 @@ public final class IllegalAccessLogger { */ private void log(Class caller, String what, Supplier msgSupplier) { // stack trace without the top-most frames in java.base - List stack = STACK_WALKER.walk(s -> + List stack = Holder.STACK_WALKER.walk(s -> s.dropWhile(this::isJavaBase) .limit(MAX_STACK_FRAMES) .collect(Collectors.toList()) @@ -184,13 +202,13 @@ public final class IllegalAccessLogger { // log message if first usage if (firstUsage) { String msg = msgSupplier.get(); - if (PRINT_STACK_TRACE) { + if (Holder.PRINT_STACK_TRACE) { synchronized (OUTPUT_LOCK) { - System.err.println(msg); - stack.forEach(f -> System.err.println("\tat " + f)); + warningStream.println(msg); + stack.forEach(f -> warningStream.println("\tat " + f)); } } else { - System.err.println(msg); + warningStream.println(msg); } } } @@ -265,8 +283,10 @@ public final class IllegalAccessLogger { * A builder for IllegalAccessLogger objects. */ public static class Builder { + private final Module UNNAMED = BootLoader.getUnnamedModule(); private Map> exported; private Map> opened; + private PrintStream warningStream = System.err; public Builder() { } @@ -276,30 +296,37 @@ public final class IllegalAccessLogger { this.opened = deepCopy(opened); } - public void logAccessToExportedPackage(Module m, String pn, String how) { - if (!m.isExported(pn)) { + public Builder logAccessToExportedPackage(Module m, String pn, String how) { + if (!m.isExported(pn, UNNAMED)) { if (exported == null) exported = new HashMap<>(); exported.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how); } + return this; } - public void logAccessToOpenPackage(Module m, String pn, String how) { + public Builder logAccessToOpenPackage(Module m, String pn, String how) { // opens implies exported at run-time. logAccessToExportedPackage(m, pn, how); - if (!m.isOpen(pn)) { + if (!m.isOpen(pn, UNNAMED)) { if (opened == null) opened = new HashMap<>(); opened.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how); } + return this; + } + + public Builder warningStream(PrintStream warningStream) { + this.warningStream = Objects.requireNonNull(warningStream); + return this; } /** * Builds the logger. */ public IllegalAccessLogger build() { - return new IllegalAccessLogger(exported, opened); + return new IllegalAccessLogger(exported, opened, warningStream); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index 0136da0f581..98f5cf0db2e 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -515,44 +515,42 @@ public final class ModuleBootstrap { * additional packages specified on the command-line. */ private static void addExtraExportsAndOpens(Layer bootLayer) { - IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder(); - // --add-exports String prefix = "jdk.module.addexports."; Map> extraExports = decode(prefix); if (!extraExports.isEmpty()) { - addExtraExportsOrOpens(bootLayer, extraExports, false, builder); + addExtraExportsOrOpens(bootLayer, extraExports, false); } // --add-opens prefix = "jdk.module.addopens."; Map> extraOpens = decode(prefix); if (!extraOpens.isEmpty()) { - addExtraExportsOrOpens(bootLayer, extraOpens, true, builder); + addExtraExportsOrOpens(bootLayer, extraOpens, true); } // --permit-illegal-access if (getAndRemoveProperty("jdk.module.permitIllegalAccess") != null) { warn("--permit-illegal-access will be removed in the next major release"); + IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder(); + Module unnamed = BootLoader.getUnnamedModule(); bootLayer.modules().stream().forEach(m -> { m.getDescriptor() .packages() .stream() - .filter(pn -> !m.isOpen(pn)) + .filter(pn -> !m.isOpen(pn, unnamed)) // skip if opened by --add-opens .forEach(pn -> { builder.logAccessToOpenPackage(m, pn, "--permit-illegal-access"); Modules.addOpensToAllUnnamed(m, pn); }); }); + IllegalAccessLogger.setIllegalAccessLogger(builder.build()); } - - IllegalAccessLogger.setIllegalAccessLogger(builder.build()); } private static void addExtraExportsOrOpens(Layer bootLayer, Map> map, - boolean opens, - IllegalAccessLogger.Builder builder) + boolean opens) { String option = opens ? ADD_OPENS : ADD_EXPORTS; for (Map.Entry> e : map.entrySet()) { @@ -600,10 +598,8 @@ public final class ModuleBootstrap { } if (allUnnamed) { if (opens) { - builder.logAccessToOpenPackage(m, pn, option); Modules.addOpensToAllUnnamed(m, pn); } else { - builder.logAccessToExportedPackage(m, pn, option); Modules.addExportsToAllUnnamed(m, pn); } } else { diff --git a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java index ed5524f7d86..c86075a260b 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -85,7 +85,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.misc.VM; -import jdk.internal.module.IllegalAccessLogger; import jdk.internal.module.Modules; @@ -429,20 +428,14 @@ public final class LauncherHelper { abort(null, "java.launcher.jar.error3", jarname); } - // Add-Exports and Add-Opens to allow illegal access + // Add-Exports and Add-Opens String exports = mainAttrs.getValue(ADD_EXPORTS); if (exports != null) { - String warn = getLocalizedMessage("java.launcher.permitaccess.warning", - jarname, ADD_EXPORTS); - System.err.println(warn); - addExportsOrOpens(exports, false, ADD_EXPORTS); + addExportsOrOpens(exports, false); } String opens = mainAttrs.getValue(ADD_OPENS); if (opens != null) { - String warn = getLocalizedMessage("java.launcher.permitaccess.warning", - jarname, ADD_OPENS); - System.err.println(warn); - addExportsOrOpens(opens, true, ADD_OPENS); + addExportsOrOpens(opens, true); } /* @@ -467,15 +460,7 @@ public final class LauncherHelper { * Process the Add-Exports or Add-Opens value. The value is * {@code / ( /)*}. */ - static void addExportsOrOpens(String value, boolean open, String how) { - IllegalAccessLogger.Builder builder; - IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger(); - if (logger == null) { - builder = new IllegalAccessLogger.Builder(); - } else { - builder = logger.toBuilder(); - } - + static void addExportsOrOpens(String value, boolean open) { for (String moduleAndPackage : value.split(" ")) { String[] s = moduleAndPackage.trim().split("/"); if (s.length == 2) { @@ -485,18 +470,14 @@ public final class LauncherHelper { Layer.boot().findModule(mn).ifPresent(m -> { if (m.getDescriptor().packages().contains(pn)) { if (open) { - builder.logAccessToOpenPackage(m, pn, how); Modules.addOpensToAllUnnamed(m, pn); } else { - builder.logAccessToExportedPackage(m, pn, how); Modules.addExportsToAllUnnamed(m, pn); } } }); } } - - IllegalAccessLogger.setIllegalAccessLogger(builder.build()); } // From src/share/bin/java.c: diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 22a6826ce87..e65926dc2a4 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -211,6 +211,4 @@ java.launcher.module.error2=\ java.launcher.module.error3=\ Error: Unable to load main class {0} from module {1}\n\ \t{2} -java.launcher.permitaccess.warning=\ - WARNING: Main manifest of {0} contains {1} attribute to permit illegal access diff --git a/jdk/test/tools/launcher/modules/permit/PermitIllegalAccess.java b/jdk/test/tools/launcher/modules/permit/PermitIllegalAccess.java index d334282bcc1..0c60c1507d4 100644 --- a/jdk/test/tools/launcher/modules/permit/PermitIllegalAccess.java +++ b/jdk/test/tools/launcher/modules/permit/PermitIllegalAccess.java @@ -29,7 +29,10 @@ * @summary Basic test for java --permit-illegal-access */ +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; import jdk.testlibrary.ProcessTools; import jdk.testlibrary.OutputAnalyzer; @@ -58,10 +61,13 @@ public class PermitIllegalAccess { * Launches AttemptAccess to execute an action, returning the OutputAnalyzer * to analyze the output/exitCode. */ - private OutputAnalyzer tryAction(String action, int count) throws Exception { - String arg = "" + count; - return ProcessTools - .executeTestJava("-cp", TEST_CLASSES, TEST_MAIN, action, arg) + private OutputAnalyzer tryAction(String action, int count, String... args) + throws Exception + { + Stream s1 = Stream.of(args); + Stream s2 = Stream.of("-cp", TEST_CLASSES, TEST_MAIN, action, "" + count); + String[] opts = Stream.concat(s1, s2).toArray(String[]::new); + return ProcessTools.executeTestJava(opts) .outputTo(System.out) .errorTo(System.out); } @@ -70,16 +76,10 @@ public class PermitIllegalAccess { * Launches AttemptAccess with --permit-illegal-access to execute an action, * returning the OutputAnalyzer to analyze the output/exitCode. */ - private OutputAnalyzer tryActionPermittingIllegalAccess(String action, - int count) + private OutputAnalyzer tryActionPermittingIllegalAccess(String action, int count) throws Exception { - String arg = "" + count; - return ProcessTools - .executeTestJava("-cp", TEST_CLASSES, "--permit-illegal-access", - TEST_MAIN, action, arg) - .outputTo(System.out) - .errorTo(System.out); + return tryAction(action, count, "--permit-illegal-access"); } /** @@ -194,6 +194,61 @@ public class PermitIllegalAccess { } + /** + * Permit access to succeed with --add-exports. No warning should be printed. + */ + public void testAccessWithAddExports() throws Exception { + tryAction("access", 1, "--add-exports", "java.base/sun.security.x509=ALL-UNNAMED") + .stdoutShouldNotContain(WARNING) + .stdoutShouldNotContain("IllegalAccessException") + .stderrShouldNotContain(WARNING) + .stderrShouldNotContain("IllegalAccessException") + .shouldHaveExitValue(0); + } + + /** + * Permit access to succeed with --add-exports and --permit-illegal-access. + * The only warning emitted should be the startup warning. + */ + public void testAccessWithePermittedAddExports() throws Exception { + tryAction("access", 1, "--permit-illegal-access", + "--add-exports", "java.base/sun.security.x509=ALL-UNNAMED") + .stdoutShouldNotContain(WARNING) + .stdoutShouldNotContain("IllegalAccessException") + .stderrShouldContain(STARTUP_WARNING) + .stderrShouldNotContain("IllegalAccessException") + .stderrShouldNotContain(ILLEGAL_ACCESS_WARNING) + .shouldHaveExitValue(0); + } + + /** + * Permit setAccessible to succeed with --add-opens. No warning should be printed. + */ + public void testSetAccessibleWithAddOpens() throws Exception { + tryAction("setAccessible", 1, "--add-opens", "java.base/java.lang=ALL-UNNAMED") + .stdoutShouldNotContain(WARNING) + .stdoutShouldNotContain("InaccessibleObjectException") + .stderrShouldNotContain(WARNING) + .stderrShouldNotContain("InaccessibleObjectException") + .shouldHaveExitValue(0); + } + + /** + * Permit setAccessible to succeed with both --add-opens and --permit-illegal-access. + * The only warning emitted should be the startup warning. + */ + public void testSetAccessiblePermittedWithAddOpens() throws Exception { + tryAction("setAccessible", 1, "--permit-illegal-access", + "--add-opens", "java.base/java.lang=ALL-UNNAMED") + .stdoutShouldNotContain(WARNING) + .stdoutShouldNotContain("InaccessibleObjectException") + .stderrShouldContain(STARTUP_WARNING) + .stderrShouldNotContain("InaccessibleObjectException") + .stderrShouldNotContain(ILLEGAL_ACCESS_WARNING) + .shouldHaveExitValue(0); + } + + /** * Returns the number of lines in the given input that contain the * given char sequence. From cc398424f9e1efe2db7259a5045f30bdc14dad54 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 24 Mar 2017 14:46:52 -0700 Subject: [PATCH 03/14] 8177564: Remove check for Windows XP and Server 2003 in java/nio/channels/DatagramChannel/NetworkConfiguration.java Remove check for XP and Server 2003 in IPv6 support determination. Reviewed-by: alanb --- .../DatagramChannel/NetworkConfiguration.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java b/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java index 6bb5c947f78..74aca295c1b 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java +++ b/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,22 +57,11 @@ class NetworkConfiguration { return ip6Interfaces.get(nif); } - // IPv6 not supported for Windows XP/Server 2003 - static boolean isIPv6Supported() { - if (System.getProperty("os.name").startsWith("Windows")) { - String ver = System.getProperty("os.version"); - int major = Integer.parseInt(ver.split("\\.")[0]); - return (major >= 6); - } - return true; - } - static NetworkConfiguration probe() throws IOException { Map> ip4Interfaces = new HashMap>(); Map> ip6Interfaces = new HashMap>(); - boolean isIPv6Supported = isIPv6Supported(); // find the interfaces that support IPv4 and IPv6 List nifs = Collections @@ -92,7 +81,7 @@ class NetworkConfiguration { } list.add(addr); ip4Interfaces.put(nif, list); - } else if (isIPv6Supported && (addr instanceof Inet6Address)) { + } else if (addr instanceof Inet6Address) { List list = ip6Interfaces.get(nif); if (list == null) { list = new LinkedList(); From b9cff83140e56d24116ac5f1015778e284987027 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 24 Mar 2017 15:02:19 -0700 Subject: [PATCH 04/14] 8177565: java/nio/channels/Selector/SelectorLimit.java disabled for Windows release >= 6.0 Remove check of Windows version Reviewed-by: alanb --- jdk/test/java/nio/channels/Selector/SelectorLimit.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/jdk/test/java/nio/channels/Selector/SelectorLimit.java b/jdk/test/java/nio/channels/Selector/SelectorLimit.java index cc34a30de11..6b7fb485294 100644 --- a/jdk/test/java/nio/channels/Selector/SelectorLimit.java +++ b/jdk/test/java/nio/channels/Selector/SelectorLimit.java @@ -66,15 +66,6 @@ public class SelectorLimit { static final int MIN_KEYS = 100; public static void main(String[] args) throws Exception { - // win9X can't handle many connections at once - String osName = System.getProperty("os.name"); - if (osName.toLowerCase().startsWith("win")) { - if (!(osName.equals("Windows NT") - || osName.equals("Windows 2000") - || osName.equals("Windows XP"))) - return; - } - ServerSocketChannel ssc = ServerSocketChannel.open(); TestUtil.bind(ssc); Listener lth = new Listener(ssc); From 340ebfef08f65602a44495f6429795e8bb953b8b Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Mon, 27 Mar 2017 15:12:01 -0700 Subject: [PATCH 05/14] 8174826: jlink support for linking in service provider modules Reviewed-by: alanb, anazarov --- .../classes/jdk/tools/jimage/JImageTask.java | 51 +-- .../jdk/tools/jlink/internal/Jlink.java | 87 ++++-- .../jdk/tools/jlink/internal/JlinkTask.java | 294 ++++++++++++++---- .../jdk/tools/jlink/internal/TaskHelper.java | 70 +++-- .../packager/AppRuntimeImageBuilder.java | 12 +- .../tools/jlink/resources/jlink.properties | 40 ++- jdk/test/tools/jlink/IntegrationTest.java | 10 +- jdk/test/tools/jlink/JLinkTest.java | 6 +- .../jlink/bindservices/BindServices.java | 200 ++++++++++++ .../jlink/bindservices/SuggestProviders.java | 209 +++++++++++++ .../bindservices/src/m1/module-info.java | 28 ++ .../jlink/bindservices/src/m1/p1/Impl.java | 30 ++ .../jlink/bindservices/src/m1/p1/Main.java | 53 ++++ .../tools/jlink/bindservices/src/m1/p1/S.java | 28 ++ .../bindservices/src/m2/module-info.java | 30 ++ .../jlink/bindservices/src/m2/p2/Impl.java | 33 ++ .../tools/jlink/bindservices/src/m2/p2/T.java | 28 ++ .../bindservices/src/m3/module-info.java | 27 ++ .../jlink/bindservices/src/m3/p3/Impl.java | 29 ++ 19 files changed, 1098 insertions(+), 167 deletions(-) create mode 100644 jdk/test/tools/jlink/bindservices/BindServices.java create mode 100644 jdk/test/tools/jlink/bindservices/SuggestProviders.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m1/module-info.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m1/p1/Impl.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m1/p1/Main.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m1/p1/S.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m2/module-info.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m2/p2/Impl.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m2/p2/T.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m3/module-info.java create mode 100644 jdk/test/tools/jlink/bindservices/src/m3/p3/Impl.java diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 344b920a8bf..c9cafff1ce2 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.MissingResourceException; import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import jdk.internal.jimage.BasicImageReader; import jdk.internal.jimage.ImageHeader; import jdk.internal.jimage.ImageLocation; @@ -99,7 +103,7 @@ class JImageTask { } static class OptionsValues { - Task task = Task.LIST; + Task task = null; String directory = "."; String include = ""; boolean fullVersion; @@ -172,24 +176,31 @@ class JImageTask { } try { - List unhandled = OPTION_HELPER.handleOptions(this, args); + String command; + String[] remaining = args; + try { + command = args[0]; + options.task = Enum.valueOf(Task.class, args[0].toUpperCase(Locale.ENGLISH)); + remaining = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) + : new String[0]; + } catch (IllegalArgumentException ex) { + command = null; + options.task = null; + } - if(!unhandled.isEmpty()) { - try { - options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); - } catch (IllegalArgumentException ex) { - throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0)); - } + // process arguments + List unhandled = OPTION_HELPER.handleOptions(this, remaining); + for (String f : unhandled) { + options.jimages.add(new File(f)); + } - for(int i = 1; i < unhandled.size(); i++) { - options.jimages.add(new File(unhandled.get(i))); - } - } else if (!options.help && !options.version && !options.fullVersion) { - throw TASK_HELPER.newBadArgs("err.invalid.task", ""); + if (options.task == null && !options.help && !options.version && !options.fullVersion) { + throw TASK_HELPER.newBadArgs("err.not.a.task", + command != null ? command : ""); } if (options.help) { - if (unhandled.isEmpty()) { + if (options.task == null) { log.println(TASK_HELPER.getMessage("main.usage", PROGNAME)); Arrays.asList(RECOGNIZED_OPTIONS).stream() .filter(option -> !option.isHidden()) @@ -203,15 +214,19 @@ class JImageTask { log.println(TASK_HELPER.getMessage("main.usage." + options.task.toString().toLowerCase())); } catch (MissingResourceException ex) { - throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0)); + throw TASK_HELPER.newBadArgs("err.not.a.task", command); } } return EXIT_OK; } if (options.version || options.fullVersion) { - TASK_HELPER.showVersion(options.fullVersion); + if (options.task == null && !unhandled.isEmpty()) { + throw TASK_HELPER.newBadArgs("err.not.a.task", + Stream.of(args).collect(Collectors.joining(" "))); + } + TASK_HELPER.showVersion(options.fullVersion); if (unhandled.isEmpty()) { return EXIT_OK; } @@ -435,7 +450,7 @@ class JImageTask { iterate(this::listTitle, null, this::verify); break; default: - throw TASK_HELPER.newBadArgs("err.invalid.task", + throw TASK_HELPER.newBadArgs("err.not.a.task", options.task.name()).showUsage(true); } return true; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java index ecb63cd0a96..5ab1bfca53a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ */ package jdk.tools.jlink.internal; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; import java.lang.reflect.Layer; import java.nio.ByteOrder; import java.nio.file.Path; @@ -33,6 +35,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; + +import jdk.internal.module.ModulePath; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.PluginException; import jdk.tools.jlink.builder.ImageBuilder; @@ -147,8 +151,8 @@ public final class Jlink { private final Path output; private final Set modules; private final Set limitmods; - private final ByteOrder endian; + private final ModuleFinder finder; /** * jlink configuration, @@ -160,31 +164,23 @@ public final class Jlink { * @param endian Jimage byte order. Native order by default */ public JlinkConfiguration(Path output, - List modulepaths, - Set modules, - Set limitmods, - ByteOrder endian) { - this.output = output; - this.modulepaths = modulepaths == null ? Collections.emptyList() : modulepaths; - this.modules = modules == null ? Collections.emptySet() : modules; - this.limitmods = limitmods == null ? Collections.emptySet() : limitmods; - this.endian = endian == null ? ByteOrder.nativeOrder() : endian; - } + List modulepaths, + Set modules, + Set limitmods, + ByteOrder endian) { + if (Objects.requireNonNull(modulepaths).isEmpty()) { + throw new IllegalArgumentException("Empty module path"); + } + if (Objects.requireNonNull(modules).isEmpty()) { + throw new IllegalArgumentException("Empty modules"); + } - /** - * jlink configuration, - * - * @param output Output directory, must not exist. - * @param modulepaths Modules paths - * @param modules Root modules to resolve - * @param limitmods Limit the universe of observable modules - */ - public JlinkConfiguration(Path output, - List modulepaths, - Set modules, - Set limitmods) { - this(output, modulepaths, modules, limitmods, - ByteOrder.nativeOrder()); + this.output = output; + this.modulepaths = modulepaths; + this.modules = modules; + this.limitmods = Objects.requireNonNull(limitmods); + this.endian = Objects.requireNonNull(endian); + this.finder = moduleFinder(); } /** @@ -222,6 +218,45 @@ public final class Jlink { return limitmods; } + /** + * Returns {@link ModuleFinder} that finds all observable modules + * for this jlink configuration. + */ + public ModuleFinder finder() { + return finder; + } + + /** + * Returns a {@link Configuration} of the given module path, + * root modules with full service binding. + */ + public Configuration resolveAndBind() + { + return Configuration.empty().resolveAndBind(finder, + ModuleFinder.of(), + modules); + } + + /** + * Returns a {@link Configuration} of the given module path, + * root modules with no service binding. + */ + public Configuration resolve() + { + return Configuration.empty().resolve(finder, + ModuleFinder.of(), + modules); + } + + private ModuleFinder moduleFinder() { + Path[] entries = modulepaths.toArray(new Path[0]); + ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries); + if (!limitmods.isEmpty()) { + finder = JlinkTask.limitFinder(finder, limitmods, modules); + } + return finder; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index 42032b6ab00..e7644ab84a7 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,6 +110,12 @@ public class JlinkTask { Path path = Paths.get(arg); task.options.output = path; }, "--output"), + new Option(false, (task, opt, arg) -> { + task.options.bindServices = true; + }, "--bind-services"), + new Option(false, (task, opt, arg) -> { + task.options.suggestProviders = true; + }, "--suggest-providers", "", true), new Option(true, (task, opt, arg) -> { String[] values = arg.split("="); // check values @@ -140,6 +146,9 @@ public class JlinkTask { throw taskHelper.newBadArgs("err.unknown.byte.order", arg); } }, "--endian"), + new Option(false, (task, opt, arg) -> { + task.options.verbose = true; + }, "--verbose", "-v"), new Option(false, (task, opt, arg) -> { task.options.version = true; }, "--version"), @@ -185,6 +194,7 @@ public class JlinkTask { static class OptionsValues { boolean help; String saveoptsfile; + boolean verbose; boolean version; boolean fullVersion; final List modulePath = new ArrayList<>(); @@ -195,6 +205,8 @@ public class JlinkTask { Path packagedModulesPath; ByteOrder endian = ByteOrder.nativeOrder(); boolean ignoreSigning = false; + boolean bindServices = false; + boolean suggestProviders = false; } int run(String[] args) { @@ -203,7 +215,11 @@ public class JlinkTask { new PrintWriter(System.err, true)); } try { - optionsHelper.handleOptionsNoUnhandled(this, args); + List remaining = optionsHelper.handleOptions(this, args); + if (remaining.size() > 0 && !options.suggestProviders) { + throw taskHelper.newBadArgs("err.orphan.arguments", toString(remaining)) + .showUsage(true); + } if (options.help) { optionsHelper.showHelp(PROGNAME); return EXIT_OK; @@ -217,17 +233,24 @@ public class JlinkTask { return EXIT_OK; } - if (taskHelper.getExistingImage() == null) { - if (options.modulePath.isEmpty()) { - throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true); - } - createImage(); - } else { + if (taskHelper.getExistingImage() != null) { postProcessOnly(taskHelper.getExistingImage()); + return EXIT_OK; } - if (options.saveoptsfile != null) { - Files.write(Paths.get(options.saveoptsfile), getSaveOpts().getBytes()); + if (options.modulePath.isEmpty()) { + throw taskHelper.newBadArgs("err.modulepath.must.be.specified") + .showUsage(true); + } + + JlinkConfiguration config = initJlinkConfig(); + if (options.suggestProviders) { + suggestProviders(config, remaining); + } else { + createImage(config); + if (options.saveoptsfile != null) { + Files.write(Paths.get(options.saveoptsfile), getSaveOpts().getBytes()); + } } return EXIT_OK; @@ -266,25 +289,13 @@ public class JlinkTask { Objects.requireNonNull(config.getOutput()); plugins = plugins == null ? new PluginsConfiguration() : plugins; - if (config.getModulepaths().isEmpty()) { - throw new IllegalArgumentException("Empty module paths"); - } - - ModuleFinder finder = newModuleFinder(config.getModulepaths(), - config.getLimitmods(), - config.getModules()); - - if (config.getModules().isEmpty()) { - throw new IllegalArgumentException("No modules to add"); - } - // First create the image provider ImageProvider imageProvider = - createImageProvider(finder, - config.getModules(), - config.getByteOrder(), + createImageProvider(config, null, IGNORE_SIGNING_DEFAULT, + false, + false, null); // Then create the Plugin Stack @@ -319,20 +330,24 @@ public class JlinkTask { // the token for "all modules on the module path" private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; - private void createImage() throws Exception { - if (options.output == null) { - throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true); - } - + private JlinkConfiguration initJlinkConfig() throws BadArgs { if (options.addMods.isEmpty()) { throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules") - .showUsage(true); + .showUsage(true); } Set roots = new HashSet<>(); for (String mod : options.addMods) { if (mod.equals(ALL_MODULE_PATH)) { - ModuleFinder finder = modulePathFinder(); + Path[] entries = options.modulePath.toArray(new Path[0]); + ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries); + if (!options.limitMods.isEmpty()) { + // finder for the observable modules specified in + // the --module-path and --limit-modules options + finder = limitFinder(finder, options.limitMods, Collections.emptySet()); + } + + // all observable modules are roots finder.findAll() .stream() .map(ModuleReference::descriptor) @@ -343,40 +358,34 @@ public class JlinkTask { } } - ModuleFinder finder = newModuleFinder(options.modulePath, - options.limitMods, - roots); + return new JlinkConfiguration(options.output, + options.modulePath, + roots, + options.limitMods, + options.endian); + } + private void createImage(JlinkConfiguration config) throws Exception { + if (options.output == null) { + throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true); + } // First create the image provider - ImageProvider imageProvider = createImageProvider(finder, - roots, - options.endian, + ImageProvider imageProvider = createImageProvider(config, options.packagedModulesPath, options.ignoreSigning, + options.bindServices, + options.verbose, log); // Then create the Plugin Stack - ImagePluginStack stack = ImagePluginConfiguration. - parseConfiguration(taskHelper.getPluginsConfig(options.output, options.launchers)); + ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration( + taskHelper.getPluginsConfig(options.output, options.launchers)); //Ask the stack to proceed stack.operate(imageProvider); } - /** - * Returns a module finder to find the observable modules specified in - * the --module-path and --limit-modules options - */ - private ModuleFinder modulePathFinder() { - Path[] entries = options.modulePath.toArray(new Path[0]); - ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries); - if (!options.limitMods.isEmpty()) { - finder = limitFinder(finder, options.limitMods, Collections.emptySet()); - } - return finder; - } - /* * Returns a module finder of the given module path that limits * the observable modules to those in the transitive closure of @@ -405,22 +414,32 @@ public class JlinkTask { return Paths.get(uri); } - private static ImageProvider createImageProvider(ModuleFinder finder, - Set roots, - ByteOrder order, + + private static ImageProvider createImageProvider(JlinkConfiguration config, Path retainModulesPath, boolean ignoreSigning, + boolean bindService, + boolean verbose, PrintWriter log) throws IOException { - if (roots.isEmpty()) { - throw new IllegalArgumentException("empty modules and limitmods"); - } + Configuration cf = bindService ? config.resolveAndBind() + : config.resolve(); - Configuration cf = Configuration.empty() - .resolve(finder, - ModuleFinder.of(), - roots); + if (verbose && log != null) { + // print modules to be linked in + cf.modules().stream() + .sorted(Comparator.comparing(ResolvedModule::name)) + .forEach(rm -> log.format("module %s (%s)%n", + rm.name(), rm.reference().location().get())); + + // print provider info + Set references = cf.modules().stream() + .map(ResolvedModule::reference).collect(Collectors.toSet()); + + String msg = String.format("%n%s:", taskHelper.getMessage("providers.header")); + printProviders(log, msg, references); + } // emit a warning for any incubating modules in the configuration if (log != null) { @@ -438,16 +457,16 @@ public class JlinkTask { Map mods = cf.modules().stream() .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation)); - return new ImageHelper(cf, mods, order, retainModulesPath, ignoreSigning); + return new ImageHelper(cf, mods, config.getByteOrder(), retainModulesPath, ignoreSigning); } /* * Returns a ModuleFinder that limits observability to the given root * modules, their transitive dependences, plus a set of other modules. */ - private static ModuleFinder limitFinder(ModuleFinder finder, - Set roots, - Set otherMods) { + public static ModuleFinder limitFinder(ModuleFinder finder, + Set roots, + Set otherMods) { // resolve all root modules Configuration cf = Configuration.empty() @@ -484,6 +503,147 @@ public class JlinkTask { }; } + /* + * Returns a map of each service type to the modules that use it + */ + private static Map> uses(Set modules) { + // collects the services used by the modules and print uses + Map> uses = new HashMap<>(); + modules.stream() + .map(ModuleReference::descriptor) + .forEach(md -> md.uses().forEach(s -> + uses.computeIfAbsent(s, _k -> new HashSet<>()).add(md.name())) + ); + return uses; + } + + private static void printProviders(PrintWriter log, + String header, + Set modules) { + printProviders(log, header, modules, uses(modules)); + } + + /* + * Prints the providers that are used by the services specified in + * the given modules. + * + * The specified uses maps a service type name to the modules + * using the service type and that may or may not be present + * the given modules. + */ + private static void printProviders(PrintWriter log, + String header, + Set modules, + Map> uses) { + if (modules.isEmpty()) + return; + + // Build a map of a service type to the provider modules + Map> providers = new HashMap<>(); + modules.stream() + .map(ModuleReference::descriptor) + .forEach(md -> { + md.provides().stream() + .filter(p -> uses.containsKey(p.service())) + .forEach(p -> providers.computeIfAbsent(p.service(), _k -> new HashSet<>()) + .add(md)); + }); + + if (!providers.isEmpty()) { + log.println(header); + } + + // print the providers of the service types used by the specified modules + // sorted by the service type name and then provider's module name + providers.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(e -> { + String service = e.getKey(); + e.getValue().stream() + .sorted(Comparator.comparing(ModuleDescriptor::name)) + .forEach(md -> + md.provides().stream() + .filter(p -> p.service().equals(service)) + .forEach(p -> log.format(" module %s provides %s, used by %s%n", + md.name(), p.service(), + uses.get(p.service()).stream() + .sorted() + .collect(Collectors.joining(",")))) + ); + }); + } + + private void suggestProviders(JlinkConfiguration config, List args) + throws BadArgs + { + if (args.size() > 1) { + throw taskHelper.newBadArgs("err.orphan.argument", + toString(args.subList(1, args.size()))) + .showUsage(true); + } + + if (options.bindServices) { + log.println(taskHelper.getMessage("no.suggested.providers")); + return; + } + + ModuleFinder finder = config.finder(); + if (args.isEmpty()) { + // print providers used by the modules resolved without service binding + Configuration cf = config.resolve(); + Set mrefs = cf.modules().stream() + .map(ResolvedModule::reference) + .collect(Collectors.toSet()); + + // print uses of the modules that would be linked into the image + mrefs.stream() + .sorted(Comparator.comparing(mref -> mref.descriptor().name())) + .forEach(mref -> { + ModuleDescriptor md = mref.descriptor(); + log.format("module %s located (%s)%n", md.name(), + mref.location().get()); + md.uses().stream().sorted() + .forEach(s -> log.format(" uses %s%n", s)); + }); + + String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header")); + printProviders(log, msg, finder.findAll(), uses(mrefs)); + + } else { + // comma-separated service types, if specified + Set names = Stream.of(args.get(0).split(",")) + .collect(Collectors.toSet()); + // find the modules that provide the specified service + Set mrefs = finder.findAll().stream() + .filter(mref -> mref.descriptor().provides().stream() + .map(ModuleDescriptor.Provides::service) + .anyMatch(names::contains)) + .collect(Collectors.toSet()); + + // the specified services may or may not be in the modules that + // would be linked in. So find uses declared in all observable modules + Map> uses = uses(finder.findAll()); + + // check if any name given on the command line are unused service + mrefs.stream() + .flatMap(mref -> mref.descriptor().provides().stream() + .map(ModuleDescriptor.Provides::service)) + .forEach(names::remove); + if (!names.isEmpty()) { + log.println(taskHelper.getMessage("warn.unused.services", + toString(names))); + } + + String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header")); + printProviders(log, msg, mrefs, uses); + } + } + + private static String toString(Collection collection) { + return collection.stream().sorted() + .collect(Collectors.joining(",")); + } + private String getSaveOpts() { StringBuilder sb = new StringBuilder(); sb.append('#').append(new Date()).append("\n"); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java index c8688ec118d..4535f9cfe7e 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import java.util.Map.Entry; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin; @@ -101,8 +102,15 @@ public final class TaskHelper { final boolean hidden; final String name; final String shortname; + final boolean terminalOption; - public Option(boolean hasArg, Processing processing, boolean hidden, String name, String shortname) { + public Option(boolean hasArg, + Processing processing, + boolean hidden, + String name, + String shortname, + boolean isTerminal) + { if (!name.startsWith("--")) { throw new RuntimeException("option name missing --, " + name); } @@ -115,24 +123,33 @@ public final class TaskHelper { this.hidden = hidden; this.name = name; this.shortname = shortname; + this.terminalOption = isTerminal; + } + + public Option(boolean hasArg, Processing processing, String name, String shortname, boolean isTerminal) { + this(hasArg, processing, false, name, shortname, isTerminal); } public Option(boolean hasArg, Processing processing, String name, String shortname) { - this(hasArg, processing, false, name, shortname); + this(hasArg, processing, false, name, shortname, false); } public Option(boolean hasArg, Processing processing, boolean hidden, String name) { - this(hasArg, processing, hidden, name, ""); + this(hasArg, processing, hidden, name, "", false); } public Option(boolean hasArg, Processing processing, String name) { - this(hasArg, processing, false, name, ""); + this(hasArg, processing, false, name, "", false); } public boolean isHidden() { return hidden; } + public boolean isTerminal() { + return terminalOption; + } + public boolean matches(String opt) { return opt.equals(name) || opt.equals(shortname) || @@ -179,12 +196,12 @@ public final class TaskHelper { private static class PluginOption extends Option { public PluginOption(boolean hasArg, Processing processing, boolean hidden, String name, String shortname) { - super(hasArg, processing, hidden, name, shortname); + super(hasArg, processing, hidden, name, shortname, false); } public PluginOption(boolean hasArg, Processing processing, boolean hidden, String name) { - super(hasArg, processing, hidden, name, ""); + super(hasArg, processing, hidden, name, "", false); } public String resourcePrefix() { @@ -498,21 +515,13 @@ public final class TaskHelper { return null; } - // used by jimage. Return unhandled arguments like "create", "describe". + /** + * Handles all options. This method stops processing the argument + * at the first non-option argument i.e. not starts with `-`, or + * at the first terminal option and returns the remaining arguments, + * if any. + */ public List handleOptions(T task, String[] args) throws BadArgs { - return handleOptions(task, args, true); - } - - // used by jlink. No unhandled arguments like "create", "describe". - void handleOptionsNoUnhandled(T task, String[] args) throws BadArgs { - handleOptions(task, args, false); - } - - // shared code that handles options for both jlink and jimage. jimage uses arguments like - // "create", "describe" etc. as "task names". Those arguments are unhandled here and returned - // as "unhandled arguments list". jlink does not want such arguments. "collectUnhandled" flag - // tells whether to allow for unhandled arguments or not. - private List handleOptions(T task, String[] args, boolean collectUnhandled) throws BadArgs { // findbugs warning, copy instead of keeping a reference. command = Arrays.copyOf(args, args.length); @@ -521,7 +530,6 @@ public final class TaskHelper { // Unit tests can call Task multiple time in same JVM. pluginOptions = new PluginsHelper(null); - List rest = collectUnhandled? new ArrayList<>() : null; // process options for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { @@ -531,7 +539,6 @@ public final class TaskHelper { if (option == null) { pluginOption = pluginOptions.getOption(name); if (pluginOption == null) { - throw new BadArgs("err.unknown.option", name). showUsage(true); } @@ -556,20 +563,23 @@ public final class TaskHelper { pluginOption.process(pluginOptions, name, param); } else { option.process(task, name, param); + if (option.isTerminal()) { + return ++i < args.length + ? Stream.of(Arrays.copyOfRange(args, i, args.length)) + .collect(Collectors.toList()) + : Collections.emptyList(); + + } } if (opt.ignoreRest()) { i = args.length; } } else { - if (collectUnhandled) { - rest.add(args[i]); - } else { - throw new BadArgs("err.orphan.argument", args[i]). - showUsage(true); - } + return Stream.of(Arrays.copyOfRange(args, i, args.length)) + .collect(Collectors.toList()); } } - return rest; + return Collections.emptyList(); } private Option getOption(String name) { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java index dd0889d3786..3632ccb16c0 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import jdk.tools.jlink.plugin.Plugin; import java.io.File; import java.io.IOException; import java.lang.module.ModuleFinder; +import java.nio.ByteOrder; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; @@ -93,9 +94,12 @@ public final class AppRuntimeImageBuilder { public void build() throws IOException { // jlink main arguments - Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration( - new File("").toPath(), // Unused - modulePath, addModules, limitModules); + Jlink.JlinkConfiguration jlinkConfig = + new Jlink.JlinkConfiguration(new File("").toPath(), // Unused + modulePath, + addModules, + limitModules, + ByteOrder.nativeOrder()); // plugin configuration List plugins = new ArrayList(); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties index 7a63cc38344..4f7558e2e04 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,12 @@ # main.usage.summary=\ -Usage: {0} --module-path --add-modules --output\n\ -\ use --help for a list of possible options +Usage: {0} --module-path --add-modules [,...]\n\ +\Use --help for a list of possible options main.usage=\ -Usage: {0} --module-path --add-modules --output\n\ -\ Possible options include: - -error.prefix=Error: -warn.prefix=Warning: +Usage: {0} --module-path --add-modules [,...]\n\ +\Possible options include: main.opt.help=\ \ -h, --help Print this help message @@ -54,9 +51,18 @@ main.opt.output=\ \ --output Location of output path main.opt.launcher=\ -\ --launcher = Launcher command name for the module\n\ -\ --launcher =/
\n\ -\ Launcher command name for the module and the main class +\ --launcher =[/]\n\ +\ Add a launcher command of the given\n\ +\ name for the module and the main class\n\ +\ if specified + +main.opt.bind-services=\ +\ --bind-services Do full service binding + +main.opt.suggest-providers=\ +\ --suggest-providers [,...] Suggest providers of services used by\n\ +\ the modules that would be linked, or\n\ +\ of the given service types main.command.files=\ \ @ Read options from file @@ -75,6 +81,9 @@ main.opt.ignore-signing-information=\ \ signed modular JARs are not copied to\n\ \ the runtime image. +main.opt.verbose=\ +\ -v, --verbose Enable verbose tracing + main.msg.bug=\ An exception has occurred in jlink. \ Please file a bug at the Java Bug Database (http://bugreport.java.com/bugreport/) \ @@ -95,6 +104,9 @@ main.extended.help.footer=\ \n\ +error.prefix=Error: +warn.prefix=Warning: + err.unknown.byte.order:unknown byte order {0} err.launcher.main.class.empty:launcher main class name cannot be empty: {0} err.launcher.module.name.empty:launcher module name cannot be empty: {0} @@ -111,12 +123,12 @@ err.file.error=cannot access file: {0} err.dir.exists={0} already exists err.badpattern=bad pattern {0} err.unknown.option=unknown option: {0} -err.orphan.argument=orphan argument: {0} err.missing.arg=no value given for {0} err.internal.error=internal error: {0} {1} {2} err.invalid.arg.for.option=invalid argument for option: {0} err.option.after.class=option must be specified before classes: {0} err.option.unsupported={0} not supported: {1} +err.orphan.arguments=invalid argument: {0} err.config.defaults=property {0} is missing from configuration err.config.defaults.value=wrong value in defaults property: {0} err.bom.generation=bom file generation failed: {0} @@ -126,3 +138,7 @@ err.signing=signed modular JAR {0} is currently not supported,\ warn.signing=WARNING: signed modular JAR {0} is currently not supported warn.invalid.arg=invalid classname or pathname not exist: {0} warn.split.package=package {0} defined in {1} {2} +warn.unused.services=Services specified in --suggest-providers not used: {0} +no.suggested.providers=--bind-services option is specified. No additional providers suggested. +suggested.providers.header=Suggested providers +providers.header=Providers diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java index c3059051986..de2c1189c66 100644 --- a/jdk/test/tools/jlink/IntegrationTest.java +++ b/jdk/test/tools/jlink/IntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.UncheckedIOException; +import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -135,11 +136,6 @@ public class IntegrationTest { } System.out.println(jl); - JlinkConfiguration config - = new JlinkConfiguration(null, null, null, null); - - System.out.println(config); - Plugin p = Jlink.newPlugin("toto", Collections.emptyMap(), null); if (p != null) { throw new Exception("Plugin should be null"); @@ -163,7 +159,7 @@ public class IntegrationTest { Set limits = new HashSet<>(); limits.add("java.management"); JlinkConfiguration config = new Jlink.JlinkConfiguration(output, - modulePaths, mods, limits, null); + modulePaths, mods, limits, ByteOrder.nativeOrder()); List lst = new ArrayList<>(); diff --git a/jdk/test/tools/jlink/JLinkTest.java b/jdk/test/tools/jlink/JLinkTest.java index 4690bb12180..a964a694a8d 100644 --- a/jdk/test/tools/jlink/JLinkTest.java +++ b/jdk/test/tools/jlink/JLinkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,7 +274,7 @@ public class JLinkTest { String[] userOptions = {"--compress", "2", "foo" }; String moduleName = "orphanarg1"; helper.generateDefaultJModule(moduleName, "composite2"); - helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: foo"); + helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: invalid argument: foo"); } // orphan argument - JDK-8166810 @@ -282,7 +282,7 @@ public class JLinkTest { String[] userOptions = {"--output", "foo", "bar" }; String moduleName = "orphanarg2"; helper.generateDefaultJModule(moduleName, "composite2"); - helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: bar"); + helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: invalid argument: bar"); } // basic check for --help - JDK-8173717 diff --git a/jdk/test/tools/jlink/bindservices/BindServices.java b/jdk/test/tools/jlink/bindservices/BindServices.java new file mode 100644 index 00000000000..1c57d211a0f --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/BindServices.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.spi.ToolProvider; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static jdk.testlibrary.Asserts.assertTrue; +import static jdk.testlibrary.ProcessTools.*; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * @test + * @bug 8174826 + * @library /lib/testlibrary + * @modules jdk.compiler jdk.jlink + * @build BindServices CompilerUtils jdk.testlibrary.ProcessTools + * @run testng BindServices + */ + +public class BindServices { + private static final String JAVA_HOME = System.getProperty("java.home"); + 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"); + + private static final String MODULE_PATH = + Paths.get(JAVA_HOME, "jmods").toString() + + File.pathSeparator + MODS_DIR.toString(); + + // the names of the modules in this test + private static String[] modules = new String[] {"m1", "m2", "m3"}; + + + private static boolean hasJmods() { + if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { + System.err.println("Test skipped. NO jmods directory"); + return false; + } + return true; + } + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Throwable { + if (!hasJmods()) return; + + for (String mn : modules) { + Path msrc = SRC_DIR.resolve(mn); + assertTrue(CompilerUtils.compile(msrc, MODS_DIR, + "--module-source-path", SRC_DIR.toString())); + } + } + + @Test + public void noServiceBinding() throws Throwable { + if (!hasJmods()) return; + + Path dir = Paths.get("noServiceBinding"); + + // no service binding and does not link m2,m3 providers. + JLink.run("--output", dir.toString(), + "--module-path", MODULE_PATH, + "--add-modules", "m1").output(); + + testImage(dir, "m1"); + } + + @Test + public void fullServiceBinding() throws Throwable { + if (!hasJmods()) return; + + Path dir = Paths.get("fullServiceBinding"); + + // full service binding + // m2 is a provider used by m1. During service binding, when m2 is + // resolved, m2 uses p2.T that causes m3 to be linked as it is a + // provider to p2.T + JLink.run("--output", dir.toString(), + "--module-path", MODULE_PATH, + "--add-modules", "m1", + "--bind-services", + "--limit-modules", "m1,m2,m3,java.base"); + + testImage(dir, "m1", "m2", "m3"); + } + + @Test + public void testVerbose() throws Throwable { + if (!hasJmods()) return; + + Path dir = Paths.get("verbose"); + + List output = + JLink.run("--output", dir.toString(), + "--module-path", MODULE_PATH, + "--add-modules", "m1", + "--bind-services", + "--verbose", + "--limit-modules", "m1,m2,m3,java.base").output(); + + List expected = List.of( + "module m1 (" + MODS_DIR.resolve("m1").toUri().toString() + ")", + "module m2 (" + MODS_DIR.resolve("m2").toUri().toString() + ")", + "module m3 (" + MODS_DIR.resolve("m3").toUri().toString() + ")", + "module m1 provides p1.S, used by m1", + "module m2 provides p1.S, used by m1", + "module m2 provides p2.T, used by m2", + "module m3 provides p2.T, used by m2" + ); + + assertTrue(output.containsAll(expected)); + + testImage(dir, "m1", "m2", "m3"); + } + + /* + * Tests the given ${java.home} to only contain the specified modules + */ + private void testImage(Path javaHome, String... modules) throws Throwable { + Path java = javaHome.resolve("bin").resolve("java"); + String[] cmd = Stream.concat( + Stream.of(java.toString(), "-m", "m1/p1.Main"), + Stream.of(modules)).toArray(String[]::new); + + assertTrue(executeProcess(cmd).outputTo(System.out) + .errorTo(System.out) + .getExitValue() == 0); + } + + static class JLink { + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); + + static JLink run(String... options) { + JLink jlink = new JLink(); + assertTrue(jlink.execute(options) == 0); + return jlink; + } + + final List output = new ArrayList<>(); + private int execute(String... options) { + System.out.println("jlink " + + Stream.of(options).collect(Collectors.joining(" "))); + + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + int rc = JLINK_TOOL.run(pw, pw, options); + System.out.println(writer.toString()); + Stream.of(writer.toString().split("\\v")) + .map(String::trim) + .forEach(output::add); + return rc; + } + + boolean contains(String s) { + return output.contains(s); + } + + List output() { + return output; + } + } +} diff --git a/jdk/test/tools/jlink/bindservices/SuggestProviders.java b/jdk/test/tools/jlink/bindservices/SuggestProviders.java new file mode 100644 index 00000000000..a1adf274925 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/SuggestProviders.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.spi.ToolProvider; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static jdk.testlibrary.Asserts.assertTrue; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * @test + * @bug 8174826 + * @library /lib/testlibrary + * @modules jdk.charsets jdk.compiler jdk.jlink + * @build SuggestProviders CompilerUtils + * @run testng SuggestProviders + */ + +public class SuggestProviders { + private static final String JAVA_HOME = System.getProperty("java.home"); + 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"); + + private static final String MODULE_PATH = + Paths.get(JAVA_HOME, "jmods").toString() + + File.pathSeparator + MODS_DIR.toString(); + + // the names of the modules in this test + private static String[] modules = new String[] {"m1", "m2", "m3"}; + + + private static boolean hasJmods() { + if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { + System.err.println("Test skipped. NO jmods directory"); + return false; + } + return true; + } + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Throwable { + if (!hasJmods()) return; + + for (String mn : modules) { + Path msrc = SRC_DIR.resolve(mn); + assertTrue(CompilerUtils.compile(msrc, MODS_DIR, + "--module-source-path", SRC_DIR.toString())); + } + } + + @Test + public void suggestProviders() throws Throwable { + if (!hasJmods()) return; + + List output = JLink.run("--module-path", MODULE_PATH, + "--add-modules", "m1", + "--suggest-providers").output(); + // check a subset of services used by java.base + List expected = List.of( + "uses java.lang.System$LoggerFinder", + "uses java.net.ContentHandlerFactory", + "uses java.net.spi.URLStreamHandlerProvider", + "uses java.nio.channels.spi.AsynchronousChannelProvider", + "uses java.nio.channels.spi.SelectorProvider", + "uses java.nio.charset.spi.CharsetProvider", + "uses java.nio.file.spi.FileSystemProvider", + "uses java.nio.file.spi.FileTypeDetector", + "uses java.security.Provider", + "uses java.util.spi.ToolProvider", + "uses p1.S", + "module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base", + "module jdk.compiler provides java.util.spi.ToolProvider, used by java.base", + "module jdk.jlink provides java.util.spi.ToolProvider, used by java.base", + "module m1 provides p1.S, used by m1", + "module m2 provides p1.S, used by m1" + ); + + assertTrue(output.containsAll(expected)); + } + + @Test + public void providersForServices() throws Throwable { + if (!hasJmods()) return; + + List output = + JLink.run("--module-path", MODULE_PATH, + "--add-modules", "m1", + "--suggest-providers", + "java.nio.charset.spi.CharsetProvider,p1.S,p2.T").output(); + + System.out.println(output); + List expected = List.of( + "module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base", + "module m1 provides p1.S, used by m1", + "module m2 provides p1.S, used by m1", + "module m2 provides p2.T, used by m2", + "module m3 provides p2.T, used by m2" + ); + + assertTrue(output.containsAll(expected)); + } + + @Test + public void unusedService() throws Throwable { + if (!hasJmods()) return; + + List output = + JLink.run("--module-path", MODULE_PATH, + "--add-modules", "m1", + "--suggest-providers", + "nonExistentType").output(); + + System.out.println(output); + List expected = List.of( + "Services specified in --suggest-providers not used: nonExistentType" + ); + + assertTrue(output.containsAll(expected)); + } + + @Test + public void noSuggestProviders() throws Throwable { + if (!hasJmods()) return; + + List output = + JLink.run("--module-path", MODULE_PATH, + "--add-modules", "m1", + "--bind-services", + "--limit-modules", "m1,m2,m3,java.base", + "--suggest-providers").output(); + + String expected = "--bind-services option is specified. No additional providers suggested."; + assertTrue(output.contains(expected)); + + } + + static class JLink { + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); + + static JLink run(String... options) { + JLink jlink = new JLink(); + assertTrue(jlink.execute(options) == 0); + return jlink; + } + + final List output = new ArrayList<>(); + private int execute(String... options) { + System.out.println("jlink " + + Stream.of(options).collect(Collectors.joining(" "))); + + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + int rc = JLINK_TOOL.run(pw, pw, options); + System.out.println(writer.toString()); + Stream.of(writer.toString().split("\\v")) + .map(String::trim) + .forEach(output::add); + return rc; + } + + boolean contains(String s) { + return output.contains(s); + } + + List output() { + return output; + } + } +} diff --git a/jdk/test/tools/jlink/bindservices/src/m1/module-info.java b/jdk/test/tools/jlink/bindservices/src/m1/module-info.java new file mode 100644 index 00000000000..59ebbe89663 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m1/module-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module m1 { + exports p1; + uses p1.S; + provides p1.S with p1.Impl; +} diff --git a/jdk/test/tools/jlink/bindservices/src/m1/p1/Impl.java b/jdk/test/tools/jlink/bindservices/src/m1/p1/Impl.java new file mode 100644 index 00000000000..b03f4e521e4 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m1/p1/Impl.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Impl implements S { + public String name() { + return this.getClass().getName(); + } +} diff --git a/jdk/test/tools/jlink/bindservices/src/m1/p1/Main.java b/jdk/test/tools/jlink/bindservices/src/m1/p1/Main.java new file mode 100644 index 00000000000..d3a07ed6601 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m1/p1/Main.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package p1; + +import java.lang.module.ModuleFinder; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * This tests if JAVA_HOME is linked only with the specified modules. + */ +public class Main { + public static void main(String... args) { + Set modules = ModuleFinder.ofSystem().findAll().stream() + .map(mref -> mref.descriptor().name()) + .filter(mn -> !mn.equals("java.base")) + .collect(Collectors.toSet()); + + Set notLinked = Stream.of(args).filter(mn -> !modules.contains(mn)) + .collect(Collectors.toSet()); + if (!notLinked.isEmpty()) { + throw new RuntimeException("Expected modules not linked in the image: " + + notLinked); + } + Stream.of(args).forEach(modules::remove); + + if (!modules.isEmpty()) { + throw new RuntimeException("Unexpected modules linked in the image: " + + modules); + } + } +} diff --git a/jdk/test/tools/jlink/bindservices/src/m1/p1/S.java b/jdk/test/tools/jlink/bindservices/src/m1/p1/S.java new file mode 100644 index 00000000000..5b43138d068 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m1/p1/S.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public interface S { + String name(); +} diff --git a/jdk/test/tools/jlink/bindservices/src/m2/module-info.java b/jdk/test/tools/jlink/bindservices/src/m2/module-info.java new file mode 100644 index 00000000000..c32e334d229 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m2/module-info.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module m2 { + requires m1; + exports p2; + uses p2.T; + provides p1.S with p2.Impl; + provides p2.T with p2.Impl; +} diff --git a/jdk/test/tools/jlink/bindservices/src/m2/p2/Impl.java b/jdk/test/tools/jlink/bindservices/src/m2/p2/Impl.java new file mode 100644 index 00000000000..d790e9ee467 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m2/p2/Impl.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p2; + +public class Impl implements p1.S, T { + public String name() { + return this.getClass().getName(); + } + + public void run() { + } +} diff --git a/jdk/test/tools/jlink/bindservices/src/m2/p2/T.java b/jdk/test/tools/jlink/bindservices/src/m2/p2/T.java new file mode 100644 index 00000000000..dea30505b32 --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m2/p2/T.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p2; + +public interface T { + void run(); +} diff --git a/jdk/test/tools/jlink/bindservices/src/m3/module-info.java b/jdk/test/tools/jlink/bindservices/src/m3/module-info.java new file mode 100644 index 00000000000..e48769209ff --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m3/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module m3 { + requires m2; + provides p2.T with p3.Impl; +} diff --git a/jdk/test/tools/jlink/bindservices/src/m3/p3/Impl.java b/jdk/test/tools/jlink/bindservices/src/m3/p3/Impl.java new file mode 100644 index 00000000000..4d328cdd71c --- /dev/null +++ b/jdk/test/tools/jlink/bindservices/src/m3/p3/Impl.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p3; + +public class Impl implements p2.T { + public void run() { + } +} From c6c3ed52eb2fcf4581b2ae5ce378d5050a3419a7 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 27 Mar 2017 18:38:58 -0700 Subject: [PATCH 06/14] 8177678: Overstatement of universality of Era.getDisplayName() implementation Reviewed-by: naoto --- .../share/classes/java/time/chrono/Era.java | 6 +++--- .../classes/java/time/chrono/JapaneseEra.java | 17 ++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/time/chrono/Era.java b/jdk/src/java.base/share/classes/java/time/chrono/Era.java index f8945fa0aec..5cf0968597c 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/Era.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/Era.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -310,8 +310,8 @@ public interface Era extends TemporalAccessor, TemporalAdjuster { * The parameters control the style of the returned text and the locale. *

* If no textual mapping is found then the {@link #getValue() numeric value} is returned. - *

- * This default implementation is suitable for all implementations. + * + * @apiNote This default implementation is suitable for most implementations. * * @param style the style of the text required, not null * @param locale the locale to use, not null diff --git a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java index 7ae62944025..e6fadc902ae 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,19 +240,10 @@ public final class JapaneseEra } /** - * Gets the textual representation of this era. - *

- * This returns the textual name used to identify the era, - * suitable for presentation to the user. - * The parameters control the style of the returned text and the locale. - *

- * If no textual mapping is found then the {@link #getValue() numeric value} - * is returned. + * {@inheritDoc} * - * @param style the style of the text required, not null - * @param locale the locale to use, not null - * @return the text value of the era, not null - * @since 9 + * @param style {@inheritDoc} + * @param locale {@inheritDoc} */ @Override public String getDisplayName(TextStyle style, Locale locale) { From 31374e10a35119118791b91275ff2b46cc96074f Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 27 Mar 2017 18:52:47 -0700 Subject: [PATCH 07/14] 8176865: overridden api has a wrong since value in java.base module Reviewed-by: alanb --- jdk/src/java.base/share/classes/java/lang/String.java | 2 -- .../share/classes/java/lang/reflect/Constructor.java | 1 - .../java.base/share/classes/java/nio/MappedByteBuffer.java | 7 ------- .../share/classes/java/nio/X-Buffer.java.template | 7 ------- .../share/classes/java/security/SecureRandom.java | 2 -- .../share/classes/java/security/SecureRandomSpi.java | 2 -- 6 files changed, 21 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index 9bcc69963c7..3dd2b9833a9 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -2672,7 +2672,6 @@ public final class String * point is passed through uninterpreted. * * @return an IntStream of char values from this sequence - * @since 9 */ @Override public IntStream chars() { @@ -2692,7 +2691,6 @@ public final class String * {@code int} values which are then passed to the stream. * * @return an IntStream of Unicode code points from this sequence - * @since 9 */ @Override public IntStream codePoints() { diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java index d60ae0eeacd..ecc3fd1f462 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java @@ -174,7 +174,6 @@ public final class Constructor extends Executable { * @throws SecurityException if the request is denied by the security manager * or this is a constructor for {@code java.lang.Class} * - * @since 9 * @spec JPMS */ @Override diff --git a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java index 838cc40a09a..07aa7c6f5b9 100644 --- a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java +++ b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java @@ -213,7 +213,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer position(int newPosition) { @@ -223,7 +222,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer limit(int newLimit) { @@ -233,7 +231,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer mark() { @@ -243,7 +240,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer reset() { @@ -253,7 +249,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer clear() { @@ -263,7 +258,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer flip() { @@ -273,7 +267,6 @@ public abstract class MappedByteBuffer /** * {@inheritDoc} - * @since 9 */ @Override public final MappedByteBuffer rewind() { diff --git a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template index 1292ca458c6..4453130953d 100644 --- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template +++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template @@ -1069,7 +1069,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public @@ -1083,7 +1082,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public @@ -1097,7 +1095,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public @@ -1111,7 +1108,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public @@ -1125,7 +1121,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public @@ -1139,7 +1134,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public @@ -1153,7 +1147,6 @@ public abstract class $Type$Buffer /** * {@inheritDoc} - * @since 9 */ @Override public diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandom.java b/jdk/src/java.base/share/classes/java/security/SecureRandom.java index 0fe361044b8..4f9f1b3a460 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java +++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java @@ -651,8 +651,6 @@ public class SecureRandom extends java.util.Random { * {@code SecureRandom}. * * @return the string representation - * - * @since 9 */ @Override public String toString() { diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java b/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java index 65a0ce0164d..fefbe576a02 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java +++ b/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java @@ -211,8 +211,6 @@ public abstract class SecureRandomSpi implements java.io.Serializable { * {@code SecureRandom}. * * @return the string representation - * - * @since 9 */ @Override public String toString() { From ec2626b88e558447f510ffb99aa5a4dcd4bbb41a Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 28 Mar 2017 09:02:59 -0700 Subject: [PATCH 08/14] 8177559: Enable java/nio/channels/Selector/OutOfBand.java for macOS >= 10.10.5 Enable test for macOS 10.10.5 and newer and remove from problem list Reviewed-by: alanb, amlu --- jdk/test/ProblemList.txt | 2 -- jdk/test/java/nio/channels/Selector/OutOfBand.java | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index d83f5106868..f16f7af5f86 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -180,8 +180,6 @@ java/nio/channels/Selector/Wakeup.java 6963118 windows- java/nio/channels/DatagramChannel/ChangingAddress.java 7141822 macosx-all -java/nio/channels/Selector/OutOfBand.java 7132677 macosx-all - java/nio/file/WatchService/Basic.java 7158947 solaris-all Solaris 11 java/nio/file/WatchService/MayFlies.java 7158947 solaris-all Solaris 11 java/nio/file/WatchService/LotsOfEvents.java 7158947 solaris-all Solaris 11 diff --git a/jdk/test/java/nio/channels/Selector/OutOfBand.java b/jdk/test/java/nio/channels/Selector/OutOfBand.java index 78322fafb92..e2d76b75b9f 100644 --- a/jdk/test/java/nio/channels/Selector/OutOfBand.java +++ b/jdk/test/java/nio/channels/Selector/OutOfBand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,9 @@ /* @test * @bug 6213702 + * @requires (os.family != "mac") | (os.version == "10.10.5") + * | (os.simpleVersion != "10.8" & os.simpleVersion != "10.9" + * & os.simpleVersion != "10.10") * @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be * selected */ From 2f4a0a94eb500191729d3619d9d55c49f69bb587 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 28 Mar 2017 17:33:48 -0700 Subject: [PATCH 09/14] 8177722: Improve grouping of jdk/internal/math tests Reviewed-by: smarks --- jdk/test/TEST.groups | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index cff9658f00b..ed7f022ac7e 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -73,6 +73,7 @@ jdk_lang = \ jdk/internal/misc \ jdk/internal/ref \ jdk/internal/jimage \ + jdk/internal/math \ jdk/modules \ vm @@ -141,8 +142,7 @@ jdk_stream = \ java/util/stream jdk_math = \ - java/math \ - jdk/internal/math + java/math jdk_io = \ java/io From 4fa7bde21bf869f596333d78013e5495cc2c6bf8 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 29 Mar 2017 13:16:12 +0100 Subject: [PATCH 10/14] 8177136: Caller sensitive method System::getLogger should specify what happens if there is no caller on the stack IllegalCallerException (instead of undocumented NPE) is thrown if there is no caller on the stack. The specification is clarified in this respect. Reviewed-by: alanb, mchung, dholmes, bchristi --- .../share/classes/java/lang/System.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 2982591e875..661c0f5a34c 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1568,6 +1568,14 @@ public final class System { * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, * java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where * {@code module} is the caller's module. + * In cases where {@code System.getLogger} is called from a context where + * there is no caller frame on the stack (e.g when called directly + * from a JNI attached thread), {@code IllegalCallerException} is thrown. + * To obtain a logger in such a context, use an auxiliary class that will + * implicitly be identified as the caller, or use the system {@link + * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead. + * Note that doing the latter may eagerly initialize the underlying + * logging system. * * @apiNote * This method may defer calling the {@link @@ -1580,6 +1588,8 @@ public final class System { * @return an instance of {@link Logger} that can be used by the calling * class. * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalCallerException if there is no Java caller frame on the + * stack. * * @since 9 */ @@ -1587,6 +1597,9 @@ public final class System { public static Logger getLogger(String name) { Objects.requireNonNull(name); final Class caller = Reflection.getCallerClass(); + if (caller == null) { + throw new IllegalCallerException("no caller frame"); + } return LazyLoggers.getLogger(name, caller.getModule()); } @@ -1600,8 +1613,16 @@ public final class System { * The returned logger will perform message localization as specified * by {@link LoggerFinder#getLocalizedLogger(java.lang.String, * java.util.ResourceBundle, java.lang.reflect.Module) - * LoggerFinder.getLocalizedLogger(name, bundle, module}, where + * LoggerFinder.getLocalizedLogger(name, bundle, module)}, where * {@code module} is the caller's module. + * In cases where {@code System.getLogger} is called from a context where + * there is no caller frame on the stack (e.g when called directly + * from a JNI attached thread), {@code IllegalCallerException} is thrown. + * To obtain a logger in such a context, use an auxiliary class that + * will implicitly be identified as the caller, or use the system {@link + * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead. + * Note that doing the latter may eagerly initialize the underlying + * logging system. * * @apiNote * This method is intended to be used after the system is fully initialized. @@ -1620,6 +1641,8 @@ public final class System { * resource bundle for message localization. * @throws NullPointerException if {@code name} is {@code null} or * {@code bundle} is {@code null}. + * @throws IllegalCallerException if there is no Java caller frame on the + * stack. * * @since 9 */ @@ -1628,6 +1651,9 @@ public final class System { final ResourceBundle rb = Objects.requireNonNull(bundle); Objects.requireNonNull(name); final Class caller = Reflection.getCallerClass(); + if (caller == null) { + throw new IllegalCallerException("no caller frame"); + } final SecurityManager sm = System.getSecurityManager(); // We don't use LazyLoggers if a resource bundle is specified. // Bootstrap sensitive classes in the JDK do not use resource bundles From 6d568376c95b205d5f9ca41e9edc78566f6e002f Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 29 Mar 2017 09:40:41 -0700 Subject: [PATCH 11/14] 8173303: Add module-subgraph images to main platform documentation Co-authored-by: Jonathan Gibbons Reviewed-by: alanb, chegar, erikj, ihse, lancea --- jdk/make/GenerateModuleSummary.gmk | 4 +- jdk/make/ModuleTools.gmk | 11 +- .../classes/build/tools/jigsaw/GenGraphs.java | 185 ++++++++++++++---- .../tools/jigsaw/javadoc-graphs.properties | 2 + .../build/tools/taglet/ModuleGraph.java | 96 +++++++++ .../java.base/share/classes/module-info.java | 1 + .../share/classes/module-info.java | 3 +- .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../java.prefs/share/classes/module-info.java | 1 + .../java.rmi/share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../java.se.ee/share/classes/module-info.java | 1 + .../java.se/share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../java.sql/share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 3 +- .../jdk.attach/share/classes/module-info.java | 1 + .../share/classes/module-info.java | 7 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../windows/classes/module-info.java | 1 + .../solaris/classes/module-info.java | 1 + .../share/classes/module-info.java | 6 + .../share/classes/module-info.java | 7 + .../jdk.jcmd/share/classes/module-info.java | 7 + .../share/classes/module-info.java | 7 + .../jdk.jdi/share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../jdk.jlink/share/classes/module-info.java | 6 + .../share/classes/module-info.java | 6 + .../jdk.jstatd/share/classes/module-info.java | 8 +- .../share/classes/module-info.java | 6 + .../share/classes/module-info.java | 6 + .../share/classes/module-info.java | 6 + .../share/classes/module-info.java | 6 + .../share/classes/module-info.java | 6 + .../jdk.net/share/classes/module-info.java | 6 + .../jdk.sctp/share/classes/module-info.java | 6 + .../share/classes/module-info.java | 1 + .../share/classes/module-info.java | 1 + .../jdk.zipfs/share/classes/module-info.java | 6 + 50 files changed, 388 insertions(+), 45 deletions(-) create mode 100644 jdk/make/src/classes/build/tools/jigsaw/javadoc-graphs.properties create mode 100644 jdk/make/src/classes/build/tools/taglet/ModuleGraph.java diff --git a/jdk/make/GenerateModuleSummary.gmk b/jdk/make/GenerateModuleSummary.gmk index 9f52ed37a74..b96e9ded8ca 100644 --- a/jdk/make/GenerateModuleSummary.gmk +++ b/jdk/make/GenerateModuleSummary.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ include MakeBase.gmk include ModuleTools.gmk GENGRAPHS_DIR := $(IMAGES_OUTPUTDIR)/gengraphs -SPEC_DOTFILES_DIR := $(IMAGES_OUTPUTDIR)/spec-dotfiles +SPEC_DOTFILES_DIR := $(GENGRAPHS_DIR)/spec-dotfiles TOOLS_MODULE_SRCDIR := $(JDK_TOPDIR)/make/src/classes/build/tools/jigsaw $(GENGRAPHS_DIR)/jdk.dot: $(BUILD_JIGSAW_TOOLS) diff --git a/jdk/make/ModuleTools.gmk b/jdk/make/ModuleTools.gmk index 45bfbae630e..c48a1b6ec3d 100644 --- a/jdk/make/ModuleTools.gmk +++ b/jdk/make/ModuleTools.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,9 @@ # questions. # -include $(SPEC) -include MakeBase.gmk +ifndef _MODULE_TOOLS_GMK +_MODULE_TOOLS_GMK := 1 + include JavaCompilation.gmk TOOLS_CLASSES_DIR := $(BUILDTOOLS_OUTPUTDIR)/tools_jigsaw_classes @@ -32,7 +33,7 @@ TOOLS_CLASSES_DIR := $(BUILDTOOLS_OUTPUTDIR)/tools_jigsaw_classes # To avoid reevaluating the compilation setup for the tools each time this file # is included, the actual compilation is handled by CompileModuleTools.gmk. The # following trick is used to be able to declare a dependency on the built tools. -BUILD_TOOLS_JDK := $(call SetupJavaCompilationCompileTarget, \ +BUILD_JIGSAW_TOOLS := $(call SetupJavaCompilationCompileTarget, \ BUILD_JIGSAW_TOOLS, $(TOOLS_CLASSES_DIR)) TOOL_GENGRAPHS := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \ @@ -47,3 +48,5 @@ TOOL_ADD_PACKAGES_ATTRIBUTE := $(BUILD_JAVA) $(JAVA_FLAGS_SMALL) \ -cp $(TOOLS_CLASSES_DIR) \ --add-exports java.base/jdk.internal.module=ALL-UNNAMED \ build.tools.jigsaw.AddPackagesAttribute + +endif # _MODULE_TOOLS_GMK diff --git a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java index 902185eef3a..8301929ebd1 100644 --- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java +++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java @@ -26,7 +26,6 @@ package build.tools.jigsaw; import com.sun.tools.jdeps.ModuleDotGraph; -import com.sun.tools.jdeps.ModuleDotGraph.DotGraphBuilder; import java.io.IOException; import java.lang.module.Configuration; @@ -36,10 +35,15 @@ import java.lang.module.ModuleReference; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; /** * Generate the DOT file for a module graph for each module in the JDK @@ -50,13 +54,19 @@ public class GenGraphs { public static void main(String[] args) throws Exception { Path dir = null; boolean spec = false; + Properties props = null; for (int i=0; i < args.length; i++) { String arg = args[i]; if (arg.equals("--spec")) { spec = true; + } else if (arg.equals("--dot-attributes")) { + if (i++ == args.length) { + throw new IllegalArgumentException("Missing argument: --dot-attributes option"); + } + props = new Properties(); + props.load(Files.newInputStream(Paths.get(args[i]))); } else if (arg.equals("--output")) { - i++; - dir = i < args.length ? Paths.get(args[i]) : null; + dir = ++i < args.length ? Paths.get(args[i]) : null; } else if (arg.startsWith("-")) { throw new IllegalArgumentException("Invalid option: " + arg); } @@ -67,11 +77,14 @@ public class GenGraphs { System.exit(1); } - // setup and configure the dot graph attributes - initDotGraphAttributes(); Files.createDirectories(dir); - - GenGraphs genGraphs = new GenGraphs(dir, spec); + ModuleGraphAttributes attributes; + if (props != null) { + attributes = new ModuleGraphAttributes(props); + } else { + attributes = new ModuleGraphAttributes(); + } + GenGraphs genGraphs = new GenGraphs(dir, spec, attributes); // print dot file for each module Map configurations = new HashMap<>(); @@ -99,49 +112,149 @@ public class GenGraphs { genGraphs.genDotFiles(configurations); } - static void initDotGraphAttributes() { - int h = 1000; - DotGraphBuilder.weight("java.se", "java.sql.rowset", h * 10); - DotGraphBuilder.weight("java.sql.rowset", "java.sql", h * 10); - DotGraphBuilder.weight("java.sql", "java.xml", h * 10); - DotGraphBuilder.weight("java.xml", "java.base", h * 10); + /** + * Custom dot file attributes. + */ + static class ModuleGraphAttributes implements ModuleDotGraph.Attributes { + static Map DEFAULT_ATTRIBUTES = Map.of( + "ranksep", "0.6", + "fontsize", "12", + "fontcolor", BLACK, + "fontname", "DejaVuSans", + "arrowsize", "1", + "arrowwidth", "2", + "arrowcolor", DARK_GRAY, + // custom + "requiresMandatedColor", LIGHT_GRAY, + "javaSubgraphColor", ORANGE, + "jdkSubgraphColor", BLUE + ); - DotGraphBuilder.sameRankNodes(Set.of("java.logging", "java.scripting", "java.xml")); - DotGraphBuilder.sameRankNodes(Set.of("java.sql")); - DotGraphBuilder.sameRankNodes(Set.of("java.compiler", "java.instrument")); - DotGraphBuilder.sameRankNodes(Set.of("java.desktop", "java.management")); - DotGraphBuilder.sameRankNodes(Set.of("java.corba", "java.xml.ws")); - DotGraphBuilder.sameRankNodes(Set.of("java.xml.bind", "java.xml.ws.annotation")); - DotGraphBuilder.setRankSep(0.7); - DotGraphBuilder.setFontSize(12); - DotGraphBuilder.setArrowSize(1); - DotGraphBuilder.setArrowWidth(2); + final Map weights = new HashMap<>(); + final List> ranks = new ArrayList<>(); + final Map attrs; + ModuleGraphAttributes(Map attrs) { + int h = 1000; + weight("java.se", "java.sql.rowset", h * 10); + weight("java.sql.rowset", "java.sql", h * 10); + weight("java.sql", "java.xml", h * 10); + weight("java.xml", "java.base", h * 10); + + ranks.add(Set.of("java.logging", "java.scripting", "java.xml")); + ranks.add(Set.of("java.sql")); + ranks.add(Set.of("java.compiler", "java.instrument")); + ranks.add(Set.of("java.desktop", "java.management")); + ranks.add(Set.of("java.corba", "java.xml.ws")); + ranks.add(Set.of("java.xml.bind", "java.xml.ws.annotation")); + + this.attrs = attrs; + } + + ModuleGraphAttributes() { + this(DEFAULT_ATTRIBUTES); + } + ModuleGraphAttributes(Properties props) { + this(toAttributes(props)); + } + + @Override + public double rankSep() { + return Double.valueOf(attrs.get("ranksep")); + } + + @Override + public int fontSize() { + return Integer.valueOf(attrs.get("fontsize")); + } + + @Override + public String fontName() { + return attrs.get("fontname"); + } + + @Override + public String fontColor() { + return attrs.get("fontcolor"); + } + + @Override + public int arrowSize() { + return Integer.valueOf(attrs.get("arrowsize")); + } + + @Override + public int arrowWidth() { + return Integer.valueOf(attrs.get("arrowwidth")); + } + + @Override + public String arrowColor() { + return attrs.get("arrowcolor"); + } + + @Override + public List> ranks() { + return ranks; + } + + @Override + public String requiresMandatedColor() { + return attrs.get("requiresMandatedColor"); + } + + @Override + public String javaSubgraphColor() { + return attrs.get("javaSubgraphColor"); + } + + @Override + public String jdkSubgraphColor() { + return attrs.get("jdkSubgraphColor"); + } + + @Override + public int weightOf(String s, String t) { + int w = weights.getOrDefault(s + ":" + t, 1); + if (w != 1) + return w; + if (s.startsWith("java.") && t.startsWith("java.")) + return 10; + return 1; + } + + public void weight(String s, String t, int w) { + weights.put(s + ":" + t, w); + } + + static Map toAttributes(Properties props) { + return DEFAULT_ATTRIBUTES.keySet().stream() + .collect(Collectors.toMap(Function.identity(), + k -> props.getProperty(k, DEFAULT_ATTRIBUTES.get(k)))); + } } private final Path dir; private final boolean spec; - GenGraphs(Path dir, boolean spec) { + private final ModuleGraphAttributes attributes; + GenGraphs(Path dir, boolean spec, ModuleGraphAttributes attributes) { this.dir = dir; this.spec = spec; + this.attributes = attributes; } void genDotFiles(Map configurations) throws IOException { ModuleDotGraph dotGraph = new ModuleDotGraph(configurations, spec); - dotGraph.genDotFiles(dir); + dotGraph.genDotFiles(dir, attributes); } + /** + * Returns true for any name if generating graph for non-spec; + * otherwise, returns true except "jdk" and name with "jdk.internal." prefix + */ boolean accept(String name, ModuleDescriptor descriptor) { - if (!spec) return true; - - if (name.equals("jdk")) - return false; - - if (name.equals("java.se") || name.equals("java.se.ee")) + if (!spec) return true; - // only the module that has exported API - return descriptor.exports().stream() - .filter(e -> !e.isQualified()) - .findAny().isPresent(); + return !name.equals("jdk") && !name.startsWith("jdk.internal."); } -} \ No newline at end of file +} diff --git a/jdk/make/src/classes/build/tools/jigsaw/javadoc-graphs.properties b/jdk/make/src/classes/build/tools/jigsaw/javadoc-graphs.properties new file mode 100644 index 00000000000..75348c3f7be --- /dev/null +++ b/jdk/make/src/classes/build/tools/jigsaw/javadoc-graphs.properties @@ -0,0 +1,2 @@ +arrowcolor=#999999 +requiresMandatedColor=#999999 diff --git a/jdk/make/src/classes/build/tools/taglet/ModuleGraph.java b/jdk/make/src/classes/build/tools/taglet/ModuleGraph.java new file mode 100644 index 00000000000..6983eaa64d2 --- /dev/null +++ b/jdk/make/src/classes/build/tools/taglet/ModuleGraph.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package build.tools.taglet; + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import javax.lang.model.element.Element; +import com.sun.source.doctree.DocTree; +import jdk.javadoc.doclet.Taglet; +import static jdk.javadoc.doclet.Taglet.Location.*; + +/** + * A block tag to optionally insert a reference to a module graph. + */ +public class ModuleGraph implements Taglet { + private static final boolean enableModuleGraph = + Boolean.getBoolean("enableModuleGraph"); + + /** Returns the set of locations in which a taglet may be used. */ + @Override + public Set getAllowedLocations() { + return EnumSet.of(MODULE); + } + + @Override + public boolean isInlineTag() { + return false; + } + + @Override + public String getName() { + return "moduleGraph"; + } + + @Override + public String toString(List tags, Element element) { + if (!enableModuleGraph) { + return ""; + } + + String moduleName = element.getSimpleName().toString(); + String imageFile = moduleName + "-graph.png"; + int thumbnailHeight = -1; + String hoverImage = ""; + if (!moduleName.equals("java.base")) { + thumbnailHeight = 100; // also appears in the stylesheet + hoverImage = "" + + getImage(moduleName, imageFile, -1, true) + + ""; + } + return "

" + + "Module Graph:\n" + + "
" + + "
" + + "" + + getImage(moduleName, imageFile, thumbnailHeight, false) + + hoverImage + + "" + + "
"; + } + + private static final String VERTICAL_ALIGN = "vertical-align:top"; + private static final String BORDER = "border: solid lightgray 1px;"; + + private String getImage(String moduleName, String file, int height, boolean useBorder) { + return String.format("\"Module", + useBorder ? BORDER + " " + VERTICAL_ALIGN : VERTICAL_ALIGN, + moduleName, + file, + (height <= 0 ? "" : " height=\"" + height + "\"")); + } +} diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 60b1512cbca..1c3f76927aa 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the foundational APIs of the Java SE Platform. * + * @moduleGraph * @since 9 */ module java.base { diff --git a/jdk/src/java.datatransfer/share/classes/module-info.java b/jdk/src/java.datatransfer/share/classes/module-info.java index 35b7571fb92..41fbc8d7b0c 100644 --- a/jdk/src/java.datatransfer/share/classes/module-info.java +++ b/jdk/src/java.datatransfer/share/classes/module-info.java @@ -24,8 +24,9 @@ */ /** - * Defines an API for transferring data between and within applications. + * Defines the API for transferring data between and within applications. * + * @moduleGraph * @since 9 */ module java.datatransfer { diff --git a/jdk/src/java.desktop/share/classes/module-info.java b/jdk/src/java.desktop/share/classes/module-info.java index 841618d8216..29d24e68df3 100644 --- a/jdk/src/java.desktop/share/classes/module-info.java +++ b/jdk/src/java.desktop/share/classes/module-info.java @@ -27,6 +27,7 @@ * Defines the AWT and Swing user interface toolkits, plus APIs for * accessibility, audio, imaging, printing, and JavaBeans. * + * @moduleGraph * @since 9 */ module java.desktop { diff --git a/jdk/src/java.instrument/share/classes/module-info.java b/jdk/src/java.instrument/share/classes/module-info.java index 4a7f2199e1d..c0a38104c13 100644 --- a/jdk/src/java.instrument/share/classes/module-info.java +++ b/jdk/src/java.instrument/share/classes/module-info.java @@ -27,6 +27,7 @@ * Defines services that allow agents to * instrument programs running on the JVM. * + * @moduleGraph * @since 9 */ module java.instrument { diff --git a/jdk/src/java.logging/share/classes/module-info.java b/jdk/src/java.logging/share/classes/module-info.java index a8120deeedb..2ddf82f4599 100644 --- a/jdk/src/java.logging/share/classes/module-info.java +++ b/jdk/src/java.logging/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Java Logging API. * + * @moduleGraph * @since 9 */ module java.logging { diff --git a/jdk/src/java.management.rmi/share/classes/module-info.java b/jdk/src/java.management.rmi/share/classes/module-info.java index fca14d540a8..ac6eabc83e3 100644 --- a/jdk/src/java.management.rmi/share/classes/module-info.java +++ b/jdk/src/java.management.rmi/share/classes/module-info.java @@ -46,6 +46,7 @@ * and load the appropriate {@code JMXConnectorServerProvider} service * implementation for the given protocol. * + * @moduleGraph * @since 9 */ module java.management.rmi { diff --git a/jdk/src/java.management/share/classes/module-info.java b/jdk/src/java.management/share/classes/module-info.java index fd8ec495098..c407821e505 100644 --- a/jdk/src/java.management/share/classes/module-info.java +++ b/jdk/src/java.management/share/classes/module-info.java @@ -29,6 +29,7 @@ * The JMX API consists of interfaces for monitoring and management of the * JVM and other components in the Java runtime. * + * @moduleGraph * @since 9 */ module java.management { diff --git a/jdk/src/java.naming/share/classes/module-info.java b/jdk/src/java.naming/share/classes/module-info.java index bd1332a5f7b..f8ec57900f0 100644 --- a/jdk/src/java.naming/share/classes/module-info.java +++ b/jdk/src/java.naming/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Java Naming and Directory Interface (JNDI) API. * + * @moduleGraph * @since 9 */ module java.naming { diff --git a/jdk/src/java.prefs/share/classes/module-info.java b/jdk/src/java.prefs/share/classes/module-info.java index 15c47ad206b..b20d962967c 100644 --- a/jdk/src/java.prefs/share/classes/module-info.java +++ b/jdk/src/java.prefs/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Preferences API. * + * @moduleGraph * @since 9 */ module java.prefs { diff --git a/jdk/src/java.rmi/share/classes/module-info.java b/jdk/src/java.rmi/share/classes/module-info.java index b10be8aee8e..6509952de9a 100644 --- a/jdk/src/java.rmi/share/classes/module-info.java +++ b/jdk/src/java.rmi/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Remote Method Invocation (RMI) API. * + * @moduleGraph * @since 9 */ module java.rmi { diff --git a/jdk/src/java.scripting/share/classes/module-info.java b/jdk/src/java.scripting/share/classes/module-info.java index 0ee7a489b1f..42854afc437 100644 --- a/jdk/src/java.scripting/share/classes/module-info.java +++ b/jdk/src/java.scripting/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Scripting API. * + * @moduleGraph * @since 9 */ module java.scripting { diff --git a/jdk/src/java.se.ee/share/classes/module-info.java b/jdk/src/java.se.ee/share/classes/module-info.java index 0156b7abe68..c12f8048963 100644 --- a/jdk/src/java.se.ee/share/classes/module-info.java +++ b/jdk/src/java.se.ee/share/classes/module-info.java @@ -29,6 +29,7 @@ * This module requires {@code java.se} and supplements it with modules * that define CORBA and Java EE APIs. These modules are upgradeable. * + * @moduleGraph * @since 9 */ @SuppressWarnings("deprecation") diff --git a/jdk/src/java.se/share/classes/module-info.java b/jdk/src/java.se/share/classes/module-info.java index 4d0d87869f3..33b99b1c13c 100644 --- a/jdk/src/java.se/share/classes/module-info.java +++ b/jdk/src/java.se/share/classes/module-info.java @@ -29,6 +29,7 @@ * The modules defining CORBA and Java EE APIs are not required by * this module, but they are required by {@code java.se.ee}. * + * @moduleGraph * @since 9 */ module java.se { diff --git a/jdk/src/java.security.jgss/share/classes/module-info.java b/jdk/src/java.security.jgss/share/classes/module-info.java index 4bb35fd807d..e73920ec79b 100644 --- a/jdk/src/java.security.jgss/share/classes/module-info.java +++ b/jdk/src/java.security.jgss/share/classes/module-info.java @@ -28,6 +28,7 @@ *

* This module also contains GSS-API mechanisms including Kerberos v5 and SPNEGO. * + * @moduleGraph * @since 9 */ module java.security.jgss { diff --git a/jdk/src/java.security.sasl/share/classes/module-info.java b/jdk/src/java.security.sasl/share/classes/module-info.java index 0f4e1fd9f1f..162f844960e 100644 --- a/jdk/src/java.security.sasl/share/classes/module-info.java +++ b/jdk/src/java.security.sasl/share/classes/module-info.java @@ -30,6 +30,7 @@ * This module also contains SASL mechanisms including DIGEST-MD5, * CRAM-MD5, and NTLM. * + * @moduleGraph * @since 9 */ module java.security.sasl { diff --git a/jdk/src/java.smartcardio/share/classes/module-info.java b/jdk/src/java.smartcardio/share/classes/module-info.java index 1b3f717e374..ece968cc733 100644 --- a/jdk/src/java.smartcardio/share/classes/module-info.java +++ b/jdk/src/java.smartcardio/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Java Smart Card I/O API. * + * @moduleGraph * @since 9 */ module java.smartcardio { diff --git a/jdk/src/java.sql.rowset/share/classes/module-info.java b/jdk/src/java.sql.rowset/share/classes/module-info.java index 5ba5fc96ecd..02413903f9c 100644 --- a/jdk/src/java.sql.rowset/share/classes/module-info.java +++ b/jdk/src/java.sql.rowset/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the JDBC RowSet API. * + * @moduleGraph * @since 9 */ module java.sql.rowset { diff --git a/jdk/src/java.sql/share/classes/module-info.java b/jdk/src/java.sql/share/classes/module-info.java index 9f3c08106c1..1e232ec122e 100644 --- a/jdk/src/java.sql/share/classes/module-info.java +++ b/jdk/src/java.sql/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the JDBC API. * + * @moduleGraph * @since 9 */ module java.sql { diff --git a/jdk/src/java.transaction/share/classes/module-info.java b/jdk/src/java.transaction/share/classes/module-info.java index 4b4d76a265a..1a3a1926248 100644 --- a/jdk/src/java.transaction/share/classes/module-info.java +++ b/jdk/src/java.transaction/share/classes/module-info.java @@ -29,6 +29,7 @@ * The subset consists of RMI exception types which are mapped to CORBA system * exceptions by the 'Java Language to IDL Mapping Specification'. * + * @moduleGraph * @since 9 */ @Deprecated(since="9", forRemoval=true) diff --git a/jdk/src/java.xml.crypto/share/classes/module-info.java b/jdk/src/java.xml.crypto/share/classes/module-info.java index ad2f50e9570..4e7db6b7579 100644 --- a/jdk/src/java.xml.crypto/share/classes/module-info.java +++ b/jdk/src/java.xml.crypto/share/classes/module-info.java @@ -24,8 +24,9 @@ */ /** - * Defines an API for XML cryptography. + * Defines the API for XML cryptography. * + * @moduleGraph * @since 9 */ module java.xml.crypto { diff --git a/jdk/src/jdk.attach/share/classes/module-info.java b/jdk/src/jdk.attach/share/classes/module-info.java index c23210ab3e8..29f0cd67a7f 100644 --- a/jdk/src/jdk.attach/share/classes/module-info.java +++ b/jdk/src/jdk.attach/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the attach API. * + * @moduleGraph * @since 9 */ module jdk.attach { diff --git a/jdk/src/jdk.charsets/share/classes/module-info.java b/jdk/src/jdk.charsets/share/classes/module-info.java index 6e8cfc36441..8d40e575d30 100644 --- a/jdk/src/jdk.charsets/share/classes/module-info.java +++ b/jdk/src/jdk.charsets/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * {@link java.nio.charset.Charset Charset} provider for the charsets that + * are not in {@code java.base} (mostly double byte and IBM charsets). + * + * @moduleGraph + * @since 9 + */ module jdk.charsets { provides java.nio.charset.spi.CharsetProvider with sun.nio.cs.ext.ExtendedCharsets; diff --git a/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java b/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java index 487df00c299..82c2cde442e 100644 --- a/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java +++ b/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * The SunPKCS11 security provider. * + * @moduleGraph * @since 9 */ module jdk.crypto.cryptoki { diff --git a/jdk/src/jdk.crypto.ec/share/classes/module-info.java b/jdk/src/jdk.crypto.ec/share/classes/module-info.java index 74601fa8faf..54f22b68609 100644 --- a/jdk/src/jdk.crypto.ec/share/classes/module-info.java +++ b/jdk/src/jdk.crypto.ec/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * The SunEC security provider. * + * @moduleGraph * @since 9 */ module jdk.crypto.ec { diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java b/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java index 20222f45122..0121f613e5e 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java @@ -26,6 +26,7 @@ /** * The SunMSCAPI security provider. * + * @moduleGraph * @since 9 */ module jdk.crypto.mscapi { diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java index 21d8a6686a2..3d96987b3c5 100644 --- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java +++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java @@ -26,6 +26,7 @@ /** * The OracleUCrypto security provider. * + * @moduleGraph * @since 9 */ module jdk.crypto.ucrypto { diff --git a/jdk/src/jdk.httpserver/share/classes/module-info.java b/jdk/src/jdk.httpserver/share/classes/module-info.java index b01a3870d79..e6c7173e8db 100644 --- a/jdk/src/jdk.httpserver/share/classes/module-info.java +++ b/jdk/src/jdk.httpserver/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the JDK-specific API for HTTP server. + * + * @moduleGraph + * @since 9 + */ module jdk.httpserver { exports com.sun.net.httpserver; diff --git a/jdk/src/jdk.jartool/share/classes/module-info.java b/jdk/src/jdk.jartool/share/classes/module-info.java index 536ca81b684..d852ee780d3 100644 --- a/jdk/src/jdk.jartool/share/classes/module-info.java +++ b/jdk/src/jdk.jartool/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * Defines tools for manipulating Java Archive (JAR) files, + * including the jar and jarsigner tools. + * + * @moduleGraph + * @since 9 + */ module jdk.jartool { exports com.sun.jarsigner; exports jdk.security.jarsigner; diff --git a/jdk/src/jdk.jcmd/share/classes/module-info.java b/jdk/src/jdk.jcmd/share/classes/module-info.java index 5edf30cec80..4cda0283f1b 100644 --- a/jdk/src/jdk.jcmd/share/classes/module-info.java +++ b/jdk/src/jdk.jcmd/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * Defines tools for diagnostics and troubleshooting a JVM, + * including the jcmd, jps, jstat and other diagnostics tools. + * + * @moduleGraph + * @since 9 + */ module jdk.jcmd { requires jdk.attach; requires jdk.internal.jvmstat; diff --git a/jdk/src/jdk.jconsole/share/classes/module-info.java b/jdk/src/jdk.jconsole/share/classes/module-info.java index 327af1e1066..7e1841a9bea 100644 --- a/jdk/src/jdk.jconsole/share/classes/module-info.java +++ b/jdk/src/jdk.jconsole/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * Defines the JMX graphical tool, jconsole, for monitoring and managing + * a running application. + * + * @moduleGraph + * @since 9 + */ module jdk.jconsole { requires transitive java.desktop; requires transitive java.management; diff --git a/jdk/src/jdk.jdi/share/classes/module-info.java b/jdk/src/jdk.jdi/share/classes/module-info.java index e2cb439d8c0..e0ea5a5e416 100644 --- a/jdk/src/jdk.jdi/share/classes/module-info.java +++ b/jdk/src/jdk.jdi/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Defines the Java Debugger Interface. * + * @moduleGraph * @since 9 */ module jdk.jdi { diff --git a/jdk/src/jdk.jdwp.agent/share/classes/module-info.java b/jdk/src/jdk.jdwp.agent/share/classes/module-info.java index b78275fab92..82d4c86056a 100644 --- a/jdk/src/jdk.jdwp.agent/share/classes/module-info.java +++ b/jdk/src/jdk.jdwp.agent/share/classes/module-info.java @@ -26,6 +26,7 @@ /** * Java Debug Wire Protocol. * + * @moduleGraph * @since 9 */ module jdk.jdwp.agent { diff --git a/jdk/src/jdk.jlink/share/classes/module-info.java b/jdk/src/jdk.jlink/share/classes/module-info.java index 00140adb802..510b4ac0bb1 100644 --- a/jdk/src/jdk.jlink/share/classes/module-info.java +++ b/jdk/src/jdk.jlink/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the Java linker tool, jlink. + * + * @moduleGraph + * @since 9 + */ module jdk.jlink { requires jdk.internal.opt; requires jdk.jdeps; diff --git a/jdk/src/jdk.jsobject/share/classes/module-info.java b/jdk/src/jdk.jsobject/share/classes/module-info.java index b8f6a2db16b..ac69396a3e5 100644 --- a/jdk/src/jdk.jsobject/share/classes/module-info.java +++ b/jdk/src/jdk.jsobject/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the API for the JavaScript Object. + * + * @moduleGraph + * @since 9 + */ module jdk.jsobject { requires java.desktop; exports netscape.javascript; diff --git a/jdk/src/jdk.jstatd/share/classes/module-info.java b/jdk/src/jdk.jstatd/share/classes/module-info.java index 67f3ec0770f..b3e3195c262 100644 --- a/jdk/src/jdk.jstatd/share/classes/module-info.java +++ b/jdk/src/jdk.jstatd/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * Defines the tool for starting a daemon for the jstat tool to monitor + * JVM statistics remotely. + * + * @moduleGraph + * @since 9 + */ module jdk.jstatd { requires java.rmi; requires jdk.internal.jvmstat; @@ -32,4 +39,3 @@ module jdk.jstatd { provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService; } - diff --git a/jdk/src/jdk.localedata/share/classes/module-info.java b/jdk/src/jdk.localedata/share/classes/module-info.java index 324e14b928f..ac27dc329c5 100644 --- a/jdk/src/jdk.localedata/share/classes/module-info.java +++ b/jdk/src/jdk.localedata/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Locale data provider for locales other than {@linkplain java.util.Locale#US US locale}. + * + * @moduleGraph + * @since 9 + */ module jdk.localedata { provides sun.util.locale.provider.LocaleDataMetaInfo with sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo, diff --git a/jdk/src/jdk.management.agent/share/classes/module-info.java b/jdk/src/jdk.management.agent/share/classes/module-info.java index 0afeaf0ccd6..81bccdb0e2b 100644 --- a/jdk/src/jdk.management.agent/share/classes/module-info.java +++ b/jdk/src/jdk.management.agent/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Define the JMX management agent. + * + * @moduleGraph + * @since 9 + */ module jdk.management.agent { requires java.management; requires java.management.rmi; diff --git a/jdk/src/jdk.management/share/classes/module-info.java b/jdk/src/jdk.management/share/classes/module-info.java index 327d31ebda8..bea31ddcadb 100644 --- a/jdk/src/jdk.management/share/classes/module-info.java +++ b/jdk/src/jdk.management/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the JDK-specific Management Interfaces for JVM. + * + * @moduleGraph + * @since 9 + */ module jdk.management { requires transitive java.management; diff --git a/jdk/src/jdk.naming.dns/share/classes/module-info.java b/jdk/src/jdk.naming.dns/share/classes/module-info.java index abe26ec2644..71d3725440a 100644 --- a/jdk/src/jdk.naming.dns/share/classes/module-info.java +++ b/jdk/src/jdk.naming.dns/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * DNS Java Naming provider. + * + * @moduleGraph + * @since 9 + */ module jdk.naming.dns { requires java.naming; diff --git a/jdk/src/jdk.naming.rmi/share/classes/module-info.java b/jdk/src/jdk.naming.rmi/share/classes/module-info.java index debe6409103..bba4557c935 100644 --- a/jdk/src/jdk.naming.rmi/share/classes/module-info.java +++ b/jdk/src/jdk.naming.rmi/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * RMI Java Naming provider. + * + * @moduleGraph + * @since 9 + */ module jdk.naming.rmi { requires java.naming; requires java.rmi; diff --git a/jdk/src/jdk.net/share/classes/module-info.java b/jdk/src/jdk.net/share/classes/module-info.java index 95fb57915a8..e5ed160d74b 100644 --- a/jdk/src/jdk.net/share/classes/module-info.java +++ b/jdk/src/jdk.net/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the JDK-specific Networking API. + * + * @moduleGraph + * @since 9 + */ module jdk.net { exports jdk.net; } diff --git a/jdk/src/jdk.sctp/share/classes/module-info.java b/jdk/src/jdk.sctp/share/classes/module-info.java index c52ceb5c8c2..f150ed25fc6 100644 --- a/jdk/src/jdk.sctp/share/classes/module-info.java +++ b/jdk/src/jdk.sctp/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the JDK-specific API for SCTP. + * + * @moduleGraph + * @since 9 + */ module jdk.sctp { exports com.sun.nio.sctp; } diff --git a/jdk/src/jdk.security.auth/share/classes/module-info.java b/jdk/src/jdk.security.auth/share/classes/module-info.java index 1f6eea6537b..59e9f996aaf 100644 --- a/jdk/src/jdk.security.auth/share/classes/module-info.java +++ b/jdk/src/jdk.security.auth/share/classes/module-info.java @@ -27,6 +27,7 @@ * Contains the implementation of the javax.security.auth.* interfaces and * various authentication modules. * + * @moduleGraph * @since 9 */ module jdk.security.auth { diff --git a/jdk/src/jdk.security.jgss/share/classes/module-info.java b/jdk/src/jdk.security.jgss/share/classes/module-info.java index f43fdd49296..3e4d520d0a4 100644 --- a/jdk/src/jdk.security.jgss/share/classes/module-info.java +++ b/jdk/src/jdk.security.jgss/share/classes/module-info.java @@ -27,6 +27,7 @@ * Defines Java extensions to the GSS-API and an implementation of the SASL * GSSAPI mechanism. * + * @moduleGraph * @since 9 */ module jdk.security.jgss { diff --git a/jdk/src/jdk.zipfs/share/classes/module-info.java b/jdk/src/jdk.zipfs/share/classes/module-info.java index 5b7275e0ccb..bcd281f459a 100644 --- a/jdk/src/jdk.zipfs/share/classes/module-info.java +++ b/jdk/src/jdk.zipfs/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Zip file system provider. + * + * @moduleGraph + * @since 9 + */ module jdk.zipfs { provides java.nio.file.spi.FileSystemProvider with jdk.nio.zipfs.ZipFileSystemProvider; } From a2173b8f39e7c5611a0366646c7a8072f0ed611f Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 29 Mar 2017 10:50:45 -0700 Subject: [PATCH 12/14] 8174148: Typo in java.util.jar.Pack200.Unpacker.properties() method documentation 8173871: Typos in Jar Packer/Unpacker PROGRESS field documentation Reviewed-by: bpb, darcy --- .../share/classes/java/util/jar/Pack200.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java index 01df2638039..c8862a8da7a 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -452,13 +452,13 @@ public abstract class Pack200 { String CODE_ATTRIBUTE_PFX = "pack.code.attribute."; /** - * The unpacker's progress as a percentage, as periodically - * updated by the unpacker. + * The packer's progress as a percentage, as periodically + * updated by the packer. * Values of 0 - 100 are normal, and -1 indicates a stall. * Progress can be monitored by polling the value of this * property. *

- * At a minimum, the unpacker must set progress to 0 + * At a minimum, the packer must set progress to 0 * at the beginning of a packing operation, and to 100 * at the end. */ @@ -623,7 +623,7 @@ public abstract class Pack200 { * property. *

* At a minimum, the unpacker must set progress to 0 - * at the beginning of a packing operation, and to 100 + * at the beginning of an unpacking operation, and to 100 * at the end. */ String PROGRESS = "unpack.progress"; @@ -631,7 +631,7 @@ public abstract class Pack200 { /** * Get the set of this engine's properties. This set is * a "live view", so that changing its - * contents immediately affects the Packer engine, and + * contents immediately affects the Unpacker engine, and * changes from the engine (such as progress indications) * are immediately visible in the map. * From 837ceec9a5832dcddd6bcb3725d7a4b37df77b3b Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 30 Mar 2017 07:29:58 +0800 Subject: [PATCH 13/14] 8177569: keytool should not warn if signature algorithm used in cacerts is weak Reviewed-by: mullan --- .../sun/security/tools/keytool/Main.java | 57 +++++++++++++------ .../sun/security/tools/keytool/WeakAlg.java | 57 +++++++++++++++++-- 2 files changed, 94 insertions(+), 20 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index c71df1a2cbe..53ea9706207 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -1025,6 +1025,13 @@ public final class Main { cf = CertificateFactory.getInstance("X509"); } + // -trustcacerts can only be specified on -importcert. + // Reset it so that warnings on CA cert will remain for + // -printcert, etc. + if (command != IMPORTCERT) { + trustcacerts = false; + } + if (trustcacerts) { caks = KeyStoreUtil.getCacertsKeyStore(); } @@ -1758,9 +1765,8 @@ public final class Main { if (keyPass == null) { keyPass = promptForKeyPass(alias, null, storePass); } - keyStore.setKeyEntry(alias, privKey, keyPass, chain); - checkWeak(rb.getString("the.generated.certificate"), chain[0]); + keyStore.setKeyEntry(alias, privKey, keyPass, chain); } /** @@ -2118,6 +2124,10 @@ public final class Main { } try { + Certificate c = srckeystore.getCertificate(alias); + if (c != null) { + checkWeak("<" + newAlias + ">", c); + } keyStore.setEntry(newAlias, entry, pp); // Place the check so that only successful imports are blocked. // For example, we don't block a failed SecretEntry import. @@ -2127,10 +2137,6 @@ public final class Main { "The.destination.pkcs12.keystore.has.different.storepass.and.keypass.Please.retry.with.destkeypass.specified.")); } } - Certificate c = srckeystore.getCertificate(alias); - if (c != null) { - checkWeak("<" + newAlias + ">", c); - } return 1; } catch (KeyStoreException kse) { Object[] source2 = {alias, kse.toString()}; @@ -2814,8 +2820,8 @@ public final class Main { } if (noprompt) { - keyStore.setCertificateEntry(alias, cert); checkWeak(rb.getString("the.input"), cert); + keyStore.setCertificateEntry(alias, cert); return true; } @@ -3049,6 +3055,11 @@ public final class Main { MessageFormat form = new MessageFormat (rb.getString(".PATTERN.printX509Cert.with.weak")); PublicKey pkey = cert.getPublicKey(); + String sigName = cert.getSigAlgName(); + // No need to warn about sigalg of a trust anchor + if (!isTrustedCert(cert)) { + sigName = withWeak(sigName); + } Object[] source = {cert.getSubjectDN().toString(), cert.getIssuerDN().toString(), cert.getSerialNumber().toString(16), @@ -3056,7 +3067,7 @@ public final class Main { cert.getNotAfter().toString(), getCertFingerPrint("SHA-1", cert), getCertFingerPrint("SHA-256", cert), - withWeak(cert.getSigAlgName()), + sigName, withWeak(pkey), cert.getVersion() }; @@ -3111,7 +3122,7 @@ public final class Main { * or null otherwise. A label is added. */ private static Pair - getTrustedSigner(Certificate cert, KeyStore ks) throws Exception { + getSigner(Certificate cert, KeyStore ks) throws Exception { if (ks.getCertificateAlias(cert) != null) { return new Pair<>("", cert); } @@ -3467,9 +3478,9 @@ public final class Main { // do we trust the cert at the top? Certificate topCert = replyCerts[replyCerts.length-1]; boolean fromKeyStore = true; - Pair root = getTrustedSigner(topCert, keyStore); + Pair root = getSigner(topCert, keyStore); if (root == null && trustcacerts && caks != null) { - root = getTrustedSigner(topCert, caks); + root = getSigner(topCert, caks); fromKeyStore = false; } if (root == null) { @@ -4301,9 +4312,19 @@ public final class Main { return result; } + private boolean isTrustedCert(Certificate cert) throws KeyStoreException { + if (caks != null && caks.getCertificateAlias(cert) != null) { + return true; + } else { + String inKS = keyStore.getCertificateAlias(cert); + return inKS != null && keyStore.isCertificateEntry(inKS); + } + } + private void checkWeak(String label, String sigAlg, Key key) { - if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) { + if (sigAlg != null && !DISABLED_CHECK.permits( + SIG_PRIMITIVE_SET, sigAlg, null)) { weakWarnings.add(String.format( rb.getString("whose.sigalg.risk"), label, sigAlg)); } @@ -4316,7 +4337,8 @@ public final class Main { } } - private void checkWeak(String label, Certificate[] certs) { + private void checkWeak(String label, Certificate[] certs) + throws KeyStoreException { for (int i = 0; i < certs.length; i++) { Certificate cert = certs[i]; if (cert instanceof X509Certificate) { @@ -4325,15 +4347,18 @@ public final class Main { if (certs.length > 1) { fullLabel = oneInMany(label, i, certs.length); } - checkWeak(fullLabel, xc.getSigAlgName(), xc.getPublicKey()); + checkWeak(fullLabel, xc); } } } - private void checkWeak(String label, Certificate cert) { + private void checkWeak(String label, Certificate cert) + throws KeyStoreException { if (cert instanceof X509Certificate) { X509Certificate xc = (X509Certificate)cert; - checkWeak(label, xc.getSigAlgName(), xc.getPublicKey()); + // No need to check the sigalg of a trust anchor + String sigAlg = isTrustedCert(cert) ? null : xc.getSigAlgName(); + checkWeak(label, sigAlg, xc.getPublicKey()); } } diff --git a/jdk/test/sun/security/tools/keytool/WeakAlg.java b/jdk/test/sun/security/tools/keytool/WeakAlg.java index 95603ba45ea..bb7ae777371 100644 --- a/jdk/test/sun/security/tools/keytool/WeakAlg.java +++ b/jdk/test/sun/security/tools/keytool/WeakAlg.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8171319 + * @bug 8171319 8177569 * @summary keytool should print out warnings when reading or generating * cert/cert req using weak algorithms * @library /test/lib @@ -78,7 +78,8 @@ public class WeakAlg { .shouldMatch(".*512-bit RSA key.*risk") .shouldContain("512-bit RSA key (weak)"); - // Multiple warnings for multiple cert in -printcert or -list or -exportcert + // Multiple warnings for multiple cert in -printcert + // or -list or -exportcert // -certreq, -printcertreq, -gencert checkCertReq("a", "", null); @@ -184,7 +185,7 @@ public class WeakAlg { .shouldMatch("The input.*MD5withRSA.*risk") .shouldNotContain("[no]"); - // cert is self-signed cacerts + // JDK-8177569: no warning for sigalg of trusted cert String weakSigAlgCA = null; KeyStore ks = KeyStoreUtil.getCacertsKeyStore(); if (ks != null) { @@ -208,12 +209,40 @@ public class WeakAlg { } } if (weakSigAlgCA != null) { + // The following 2 commands still have a warning on why not using + // the -cacerts option directly. + kt("-list -keystore " + KeyStoreUtil.getCacerts()) + .shouldNotContain("risk"); + kt("-list -v -keystore " + KeyStoreUtil.getCacerts()) + .shouldNotContain("risk"); + + // -printcert will always show warnings + kt("-printcert -file ca.cert") + .shouldContain("name: " + weakSigAlgCA + " (weak)") + .shouldContain("Warning") + .shouldMatch("The certificate.*" + weakSigAlgCA + ".*risk"); + kt("-printcert -file ca.cert -trustcacerts") // -trustcacerts useless + .shouldContain("name: " + weakSigAlgCA + " (weak)") + .shouldContain("Warning") + .shouldMatch("The certificate.*" + weakSigAlgCA + ".*risk"); + + // Importing with -trustcacerts ignore CA cert's sig alg kt("-delete -alias d"); kt("-importcert -alias d -trustcacerts -file ca.cert", "no") .shouldContain("Certificate already exists in system-wide CA") + .shouldNotContain("risk") + .shouldContain("Do you still want to add it to your own keystore?"); + kt("-importcert -alias d -trustcacerts -file ca.cert -noprompt") + .shouldNotContain("risk") + .shouldNotContain("[no]"); + + // but not without -trustcacerts + kt("-delete -alias d"); + kt("-importcert -alias d -file ca.cert", "no") + .shouldContain("name: " + weakSigAlgCA + " (weak)") .shouldContain("Warning") .shouldMatch("The input.*" + weakSigAlgCA + ".*risk") - .shouldContain("Do you still want to add it to your own keystore?"); + .shouldContain("Trust this certificate?"); kt("-importcert -alias d -file ca.cert -noprompt") .shouldContain("Warning") .shouldMatch("The input.*" + weakSigAlgCA + ".*risk") @@ -265,6 +294,26 @@ public class WeakAlg { // install reply + reStore(); + certreq("c", ""); + gencert("a-c", ""); + kt("-importcert -alias c -file a-c.cert") + .shouldContain("Warning") + .shouldMatch("Issuer .*MD5withRSA.*risk"); + + // JDK-8177569: no warning for sigalg of trusted cert + reStore(); + // Change a into a TrustedCertEntry + kt("-exportcert -alias a -file a.cert"); + kt("-delete -alias a"); + kt("-importcert -alias a -file a.cert -noprompt"); + kt("-list -alias a -v") + .shouldNotContain("weak") + .shouldNotContain("Warning"); + // This time a is trusted and no warning on its weak sig alg + kt("-importcert -alias c -file a-c.cert") + .shouldNotContain("Warning"); + reStore(); gencert("a-b", ""); From a1c69dba88eb6ba0c788c446fcc1f10e3a96c7b7 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Wed, 29 Mar 2017 23:33:06 +0000 Subject: [PATCH 14/14] Added tag jdk-9+163 for changeset b5c4e28a7521 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 81e51863746..de92f56c630 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -405,3 +405,4 @@ c476ca73750698fa5654e101af699ee45db38e2a jdk-9+158 cac788454598b95d8b0153c021a7fae3cd7e6fda jdk-9+160 09b92d3067a38ee07bc14efa336b14790c93f7e7 jdk-9+161 f6bf027e88e9a4dd19f721001a7af00157af42c4 jdk-9+162 +50171f8c47961710cbf87aead6f03fa431d8d240 jdk-9+163