# HG changeset patch # User mchung # Date 1483552221 28800 # Node ID d761de69e27f7bf0b9d35366a1aef8376bbd6e2d # Parent c692f1d73e143ed91ba6b82daf96c6e9b8bb3395 8172215: java launcher no longer accepts -cp "" empty string Reviewed-by: alanb, dholmes, psandoz diff -r c692f1d73e14 -r d761de69e27f jdk/src/java.base/share/native/libjli/java.c --- a/jdk/src/java.base/share/native/libjli/java.c Wed Jan 04 18:32:19 2017 +0100 +++ b/jdk/src/java.base/share/native/libjli/java.c Wed Jan 04 09:50:21 2017 -0800 @@ -1248,6 +1248,7 @@ char *value = NULL; int kind = GetOpt(&argc, &argv, &option, &value); jboolean has_arg = value != NULL && JLI_StrLen(value) > 0; + jboolean has_arg_any_len = value != NULL; /* * Option to set main entry point @@ -1269,7 +1270,7 @@ JLI_StrCCmp(arg, "--class-path=") == 0 || JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { - REPORT_ERROR (has_arg, ARG_ERROR1, arg); + REPORT_ERROR (has_arg_any_len, ARG_ERROR1, arg); SetClassPath(value); mode = LM_CLASS; } else if (JLI_StrCmp(arg, "--list-modules") == 0 || diff -r c692f1d73e14 -r d761de69e27f jdk/test/lib/testlibrary/ModuleInfoMaker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/lib/testlibrary/ModuleInfoMaker.java Wed Jan 04 09:50:21 2017 -0800 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import static org.testng.Assert.assertTrue; + +/** + * Utility class for creating test modules. + */ +public class ModuleInfoMaker { + private static String MODULE_INFO_JAVA = "module-info.java"; + private static Pattern MODULE_PATTERN = + Pattern.compile("module\\s+((?:\\w+\\.)*)"); + private static Pattern PACKAGE_PATTERN = + Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); + private static Pattern CLASS_PATTERN = + Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)"); + + private final Path dir; + public ModuleInfoMaker(Path dir) { + this.dir = dir; + } + + /** + * Create java source files of the given module + */ + public void writeJavaFiles(String module, String moduleInfoJava, String... contents) + throws IOException + { + Path msrc = dir.resolve(module); + new JavaSource(moduleInfoJava).write(msrc); + for (String c : contents) { + new JavaSource(c).write(msrc); + } + } + + /** + * Compile the module to the given destination. + */ + public void compile(String module, Path dest, String... options) + throws IOException + { + Path msrc = dir.resolve(module); + Stream args = + Stream.concat(Arrays.stream(options), + Stream.of("--module-source-path", + dir.toString())); + assertTrue(CompilerUtils.compile(msrc, dest, args.toArray(String[]::new)), + "Fail to compile " + module); + } + + static class JavaSource { + final String source; + JavaSource(String source) { + this.source = source; + } + + /** + * Writes the source code to a file in a specified directory. + * @param dir the directory + * @throws IOException if there is a problem writing the file + */ + public void write(Path dir) throws IOException { + Path file = dir.resolve(getJavaFileNameFromSource(source)); + Files.createDirectories(file.getParent()); + try (BufferedWriter out = Files.newBufferedWriter(file)) { + out.write(source.replace("\n", System.lineSeparator())); + } + } + + /** + * Extracts the Java file name from the class declaration. + * This method is intended for simple files and uses regular expressions, + * so comments matching the pattern can make the method fail. + */ + static String getJavaFileNameFromSource(String source) { + String packageName = null; + + Matcher matcher = MODULE_PATTERN.matcher(source); + if (matcher.find()) + return MODULE_INFO_JAVA; + + matcher = PACKAGE_PATTERN.matcher(source); + if (matcher.find()) + packageName = matcher.group(1).replace(".", "/"); + + matcher = CLASS_PATTERN.matcher(source); + if (matcher.find()) { + String className = matcher.group(1) + ".java"; + return (packageName == null) ? className : packageName + "/" + className; + } else if (packageName != null) { + return packageName + "/package-info.java"; + } else { + throw new Error("Could not extract the java class " + + "name from the provided source"); + } + } + } +} diff -r c692f1d73e14 -r d761de69e27f jdk/test/lib/testlibrary/ModuleSourceBuilder.java --- a/jdk/test/lib/testlibrary/ModuleSourceBuilder.java Wed Jan 04 18:32:19 2017 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import static org.testng.Assert.assertTrue; - -/** - * Utility class for creating test modules. - */ -public class ModuleSourceBuilder { - private static String MODULE_INFO_JAVA = "module-info.java"; - private static Pattern MODULE_PATTERN = - Pattern.compile("module\\s+((?:\\w+\\.)*)"); - private static Pattern PACKAGE_PATTERN = - Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); - private static Pattern CLASS_PATTERN = - Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)"); - - private final Path dir; - public ModuleSourceBuilder(Path dir) { - this.dir = dir; - } - - /** - * Create java source files of the given module - */ - public void writeJavaFiles(String module, String moduleInfoJava, String... contents) - throws IOException - { - Path msrc = dir.resolve(module); - new JavaSource(moduleInfoJava).write(msrc); - for (String c : contents) { - new JavaSource(c).write(msrc); - } - } - - /** - * Compile the module to the given destination. - */ - public void compile(String module, Path dest, String... options) - throws IOException - { - Path msrc = dir.resolve(module); - Stream args = - Stream.concat(Arrays.stream(options), - Stream.of("--module-source-path", - dir.toString())); - assertTrue(CompilerUtils.compile(msrc, dest, args.toArray(String[]::new)), - "Fail to compile " + module); - } - - static class JavaSource { - final String source; - JavaSource(String source) { - this.source = source; - } - - /** - * Writes the source code to a file in a specified directory. - * @param dir the directory - * @throws IOException if there is a problem writing the file - */ - public void write(Path dir) throws IOException { - Path file = dir.resolve(getJavaFileNameFromSource(source)); - Files.createDirectories(file.getParent()); - try (BufferedWriter out = Files.newBufferedWriter(file)) { - out.write(source.replace("\n", System.lineSeparator())); - } - } - - /** - * Extracts the Java file name from the class declaration. - * This method is intended for simple files and uses regular expressions, - * so comments matching the pattern can make the method fail. - */ - static String getJavaFileNameFromSource(String source) { - String packageName = null; - - Matcher matcher = MODULE_PATTERN.matcher(source); - if (matcher.find()) - return MODULE_INFO_JAVA; - - matcher = PACKAGE_PATTERN.matcher(source); - if (matcher.find()) - packageName = matcher.group(1).replace(".", "/"); - - matcher = CLASS_PATTERN.matcher(source); - if (matcher.find()) { - String className = matcher.group(1) + ".java"; - return (packageName == null) ? className : packageName + "/" + className; - } else if (packageName != null) { - return packageName + "/package-info.java"; - } else { - throw new Error("Could not extract the java class " + - "name from the provided source"); - } - } - } -} diff -r c692f1d73e14 -r d761de69e27f jdk/test/tools/launcher/modules/addexports/AddExportsTestWarningError.java --- a/jdk/test/tools/launcher/modules/addexports/AddExportsTestWarningError.java Wed Jan 04 18:32:19 2017 +0100 +++ b/jdk/test/tools/launcher/modules/addexports/AddExportsTestWarningError.java Wed Jan 04 09:50:21 2017 -0800 @@ -27,7 +27,7 @@ * @summary Basic argument validation for --add-exports * @library /lib/testlibrary * @modules jdk.compiler - * @build AddExportsTestWarningError CompilerUtils ModuleSourceBuilder + * @build AddExportsTestWarningError CompilerUtils ModuleInfoMaker * @build jdk.testlibrary.* * @run testng AddExportsTestWarningError */ @@ -59,7 +59,7 @@ @BeforeTest public void setup() throws Exception { - ModuleSourceBuilder builder = new ModuleSourceBuilder(SRC_DIR); + ModuleInfoMaker builder = new ModuleInfoMaker(SRC_DIR); builder.writeJavaFiles("m1", "module m1 { }", "package p1; public class C1 { " + diff -r c692f1d73e14 -r d761de69e27f jdk/test/tools/launcher/modules/addreads/AddReadsTestWarningError.java --- a/jdk/test/tools/launcher/modules/addreads/AddReadsTestWarningError.java Wed Jan 04 18:32:19 2017 +0100 +++ b/jdk/test/tools/launcher/modules/addreads/AddReadsTestWarningError.java Wed Jan 04 09:50:21 2017 -0800 @@ -27,7 +27,7 @@ * @summary Basic argument validation for --add-reads * @library /lib/testlibrary * @modules jdk.compiler - * @build AddReadsTestWarningError CompilerUtils ModuleSourceBuilder + * @build AddReadsTestWarningError CompilerUtils ModuleInfoMaker * @build jdk.testlibrary.* * @run testng AddReadsTestWarningError */ @@ -59,7 +59,7 @@ @BeforeTest public void setup() throws Exception { - ModuleSourceBuilder builder = new ModuleSourceBuilder(SRC_DIR); + ModuleInfoMaker builder = new ModuleInfoMaker(SRC_DIR); builder.writeJavaFiles("m1", "module m1 { requires m4; }", "package p1; public class C1 { " + diff -r c692f1d73e14 -r d761de69e27f jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java --- a/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java Wed Jan 04 18:32:19 2017 +0100 +++ b/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java Wed Jan 04 09:50:21 2017 -0800 @@ -95,19 +95,20 @@ public Object[][] classpath() { return new Object[][]{ // true indicates that class path default to current working directory - { "", "." }, - { "-Djava.class.path", "." }, - { "-Djava.class.path=", "" }, - { "-Djava.class.path=.", "." }, + { List.of(), "." }, + { List.of("-cp", ""), "" }, + { List.of("-cp", "."), "." }, + { List.of("-Djava.class.path"), "." }, + { List.of("-Djava.class.path="), "" }, + { List.of("-Djava.class.path=."), "." }, }; } @Test(dataProvider = "classpath") - public void testUnnamedModule(String option, String expected) throws Throwable { - List args = new ArrayList<>(); - if (!option.isEmpty()) { - args.add(option); - } + public void testUnnamedModule(List options, String expected) + throws Throwable + { + List args = new ArrayList<>(options); args.add(TEST_MAIN); args.add(Boolean.toString(true)); args.add(expected); @@ -195,8 +196,12 @@ } private OutputAnalyzer execute(List options) throws Throwable { - ProcessBuilder pb = - createJavaProcessBuilder(options.toArray(new String[0])); + ProcessBuilder pb = createJavaProcessBuilder( + options.stream() + .map(this::autoQuote) + .toArray(String[]::new) + ); + Map env = pb.environment(); // remove CLASSPATH environment variable String value = env.remove("CLASSPATH"); @@ -205,4 +210,16 @@ .errorTo(System.out); } + private static final boolean IS_WINDOWS + = System.getProperty("os.name").startsWith("Windows"); + + /* + * Autoquote empty string argument on Windows + */ + private String autoQuote(String arg) { + if (IS_WINDOWS && arg.isEmpty()) { + return "\"\""; + } + return arg; + } }