# HG changeset patch # User alanb # Date 1497630098 25200 # Node ID abaedfca9e3e6287f612ba44d3c473c49e74a43b # Parent da99b31da7b5a9601f90eb0d2da701ea32b9687b 8181087: Module system implementation refresh (6/2017) Reviewed-by: jjg Contributed-by: alan.bateman@oracle.com, jan.lahoda@oracle.com diff -r da99b31da7b5 -r abaedfca9e3e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu Jun 15 17:24:13 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Fri Jun 16 09:21:38 2017 -0700 @@ -1574,8 +1574,13 @@ : null; DiagnosticPosition pos = env != null ? env.tree.pos() : null; try { - log.error(pos, Errors.PackageClashFromRequires(msym, packageName, - previousModule, exportsFrom)); + if (msym.isUnnamed()) { + log.error(pos, Errors.PackageClashFromRequiresInUnnamed(packageName, + previousModule, exportsFrom)); + } else { + log.error(pos, Errors.PackageClashFromRequires(msym, packageName, + previousModule, exportsFrom)); + } } finally { if (env != null) log.useSource(origSource); diff -r da99b31da7b5 -r abaedfca9e3e src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Jun 15 17:24:13 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Fri Jun 16 09:21:38 2017 -0700 @@ -29,6 +29,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.net.URI; import java.net.URL; @@ -65,6 +66,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.jar.Attributes; +import java.util.jar.Manifest; import javax.lang.model.SourceVersion; import javax.tools.JavaFileManager; @@ -1341,6 +1344,24 @@ String moduleName = readModuleName(moduleInfoClass); return new Pair<>(moduleName, p); } + Path mf = fs.getPath("META-INF/MANIFEST.MF"); + if (Files.exists(mf)) { + try (InputStream in = Files.newInputStream(mf)) { + Manifest man = new Manifest(in); + Attributes attrs = man.getMainAttributes(); + if (attrs != null) { + String moduleName = attrs.getValue(new Attributes.Name("Automatic-Module-Name")); + if (moduleName != null) { + if (isModuleName(moduleName)) { + return new Pair<>(moduleName, p); + } else { + log.error(Errors.LocnCantGetModuleNameForJar(p)); + return null; + } + } + } + } + } } catch (ModuleNameReader.BadClassFile e) { log.error(Errors.LocnBadModuleInfo(p)); return null; @@ -1428,6 +1449,22 @@ } } + //from jdk.internal.module.Checks: + /** + * Returns {@code true} if the given name is a legal module name. + */ + private boolean isModuleName(String name) { + int next; + int off = 0; + while ((next = name.indexOf('.', off)) != -1) { + String id = name.substring(off, next); + if (!SourceVersion.isName(id)) + return false; + off = next+1; + } + String last = name.substring(off); + return SourceVersion.isName(last); + } } private class ModuleSourcePathLocationHandler extends BasicLocationHandler { diff -r da99b31da7b5 -r abaedfca9e3e src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Jun 15 17:24:13 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Jun 16 09:21:38 2017 -0700 @@ -2990,6 +2990,10 @@ compiler.err.package.clash.from.requires=\ module {0} reads package {1} from both {2} and {3} +# 0: name, 1: symbol, 2: symbol +compiler.err.package.clash.from.requires.in.unnamed=\ + the unnamed module reads package {0} from both {1} and {2} + # 0: string compiler.err.module.not.found.in.module.source.path=\ module {0} not found in module source path diff -r da99b31da7b5 -r abaedfca9e3e src/jdk.jdeps/share/classes/module-info.java --- a/src/jdk.jdeps/share/classes/module-info.java Thu Jun 15 17:24:13 2017 +0000 +++ b/src/jdk.jdeps/share/classes/module-info.java Fri Jun 16 09:21:38 2017 -0700 @@ -30,11 +30,9 @@ * @since 9 */ module jdk.jdeps { - requires java.base; requires java.compiler; requires jdk.compiler; - exports com.sun.tools.classfile to - jdk.jlink; + exports com.sun.tools.classfile to jdk.jlink; provides java.util.spi.ToolProvider with com.sun.tools.javap.Main.JavapToolProvider, diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/PackageClashFromRequiresInUnnamed.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/PackageClashFromRequiresInUnnamed.java Fri Jun 16 09:21:38 2017 -0700 @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// key: compiler.err.package.clash.from.requires.in.unnamed +// options: --add-modules ALL-MODULE-PATH diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib1x/exported/Api1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib1x/exported/Api1.java Fri Jun 16 09:21:38 2017 -0700 @@ -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. + */ + +package exported; + +public class Api1 { +} diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib1x/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib1x/module-info.java Fri Jun 16 09:21:38 2017 -0700 @@ -0,0 +1,26 @@ +/* + * 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 lib1x { + exports exported; +} diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib2x/exported/Api2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib2x/exported/Api2.java Fri Jun 16 09:21:38 2017 -0700 @@ -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. + */ + +package exported; + +public class Api2 { +} diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib2x/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/PackageClashFromRequiresInUnnamed/modulepath/lib2x/module-info.java Fri Jun 16 09:21:38 2017 -0700 @@ -0,0 +1,26 @@ +/* + * 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 lib2x { + exports exported; +} diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/modules/AutomaticModules.java --- a/test/tools/javac/modules/AutomaticModules.java Thu Jun 15 17:24:13 2017 +0000 +++ b/test/tools/javac/modules/AutomaticModules.java Fri Jun 16 09:21:38 2017 -0700 @@ -34,14 +34,18 @@ * @run main AutomaticModules */ +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import toolbox.JarTask; import toolbox.JavacTask; import toolbox.Task; +import toolbox.Task.Mode; public class AutomaticModules extends ModuleTestBase { @@ -614,4 +618,204 @@ } } + @Test + public void testAutomaticModuleNameCorrect(Path base) throws Exception { + Path modulePath = base.resolve("module-path"); + + Files.createDirectories(modulePath); + + Path automaticSrc = base.resolve("automaticSrc"); + tb.writeJavaFiles(automaticSrc, "package api; public class Api {}"); + Path automaticClasses = base.resolve("automaticClasses"); + tb.createDirectories(automaticClasses); + + String automaticLog = new JavacTask(tb) + .outdir(automaticClasses) + .files(findJavaFiles(automaticSrc)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!automaticLog.isEmpty()) + throw new Exception("expected output not found: " + automaticLog); + + Path automaticJar = modulePath.resolve("automatic-1.0.jar"); + + new JarTask(tb, automaticJar) + .baseDir(automaticClasses) + .files("api/Api.class") + .manifest("Automatic-Module-Name: custom.module.name\n\n") + .run(); + + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + "module m { requires custom.module.name; }", + "package impl; public class Impl { api.Api a; }"); + + Path classes = base.resolve("classes"); + + Files.createDirectories(classes); + + new JavacTask(tb) + .options("--module-path", modulePath.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + tb.writeJavaFiles(src, + "module m { requires automatic; }"); + + List log = new JavacTask(tb) + .options("--module-path", modulePath.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = + Arrays.asList("module-info.java:1:21: compiler.err.module.not.found: automatic", + "1 error"); + + if (!expected.equals(log)) { + throw new Exception("expected output not found: " + log); + } + } + + @Test + public void testAutomaticModuleNameIncorrect(Path base) throws Exception { + for (String name : new String[] {"", "999", "foo.class", "foo._"}) { + if (Files.isDirectory(base)) { + tb.cleanDirectory(base); + } + Path modulePath = base.resolve("module-path"); + + Files.createDirectories(modulePath); + + Path automaticSrc = base.resolve("automaticSrc"); + tb.writeJavaFiles(automaticSrc, "package api; public class Api {}"); + Path automaticClasses = base.resolve("automaticClasses"); + tb.createDirectories(automaticClasses); + + String automaticLog = new JavacTask(tb) + .outdir(automaticClasses) + .files(findJavaFiles(automaticSrc)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!automaticLog.isEmpty()) + throw new Exception("expected output not found: " + automaticLog); + + Path automaticJar = modulePath.resolve("automatic-1.0.jar"); + + new JarTask(tb, automaticJar) + .baseDir(automaticClasses) + .files("api/Api.class") + .manifest("Automatic-Module-Name: " + name + "\n\n") + .run(); + + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + "package impl; public class Impl { api.Api a; }"); + + Path classes = base.resolve("classes"); + + Files.createDirectories(classes); + + List log = new JavacTask(tb, Mode.CMDLINE) + .options("--module-path", modulePath.toString(), + "--add-modules", "ALL-MODULE-PATH", + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = + Arrays.asList("- compiler.err.locn.cant.get.module.name.for.jar: " + + "testAutomaticModuleNameIncorrect/module-path/automatic-1.0.jar".replace("/", File.separator), + "1 error"); + + if (!expected.equals(log)) { + throw new Exception("expected output not found: " + log); + } + } + } + + @Test + public void testAutomaticModuleNameBroken(Path base) throws Exception { + Path modulePath = base.resolve("module-path"); + + Files.createDirectories(modulePath); + + Path automaticSrc = base.resolve("automaticSrc"); + tb.writeJavaFiles(automaticSrc, "package api; public class Api {}"); + Path automaticClasses = base.resolve("automaticClasses"); + tb.createDirectories(automaticClasses); + + String automaticLog = new JavacTask(tb) + .outdir(automaticClasses) + .files(findJavaFiles(automaticSrc)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!automaticLog.isEmpty()) + throw new Exception("expected output not found: " + automaticLog); + + Path automaticJar = modulePath.resolve("automatic-1.0.jar"); + + try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(automaticJar))) { + out.putNextEntry(new ZipEntry("api/Api.class")); + Files.copy(automaticClasses.resolve("api").resolve("Api.class"), out); + } + + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + "module m { requires automatic; }", + "package impl; public class Impl { api.Api a; }"); + + Path classes = base.resolve("classes"); + + Files.createDirectories(classes); + + new JavacTask(tb) + .options("--module-path", modulePath.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + tb.writeJavaFiles(src, + "module m { requires custom.module.name; }"); + + List log = new JavacTask(tb) + .options("--module-path", modulePath.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = + Arrays.asList("module-info.java:1:34: compiler.err.module.not.found: custom.module.name", + "1 error"); + + if (!expected.equals(log)) { + throw new Exception("expected output not found: " + log); + } + } + } diff -r da99b31da7b5 -r abaedfca9e3e test/tools/javac/modules/PackageConflictTest.java --- a/test/tools/javac/modules/PackageConflictTest.java Thu Jun 15 17:24:13 2017 +0000 +++ b/test/tools/javac/modules/PackageConflictTest.java Fri Jun 16 09:21:38 2017 -0700 @@ -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 @@ -277,4 +277,57 @@ throw new Exception("expected output not found"); } } + + @Test + public void testConflictInDependenciesInUnnamed(Path base) throws Exception { + Path msp = base.resolve("module-path-source"); + Path m1 = msp.resolve("m1x"); + Path m2 = msp.resolve("m2x"); + tb.writeJavaFiles(m1, + "module m1x { exports test; }", + "package test; public class A { }"); + tb.writeJavaFiles(m2, + "module m2x { exports test; }", + "package test; public class B { }"); + Path mp = base.resolve("module-path"); + Files.createDirectories(mp); + + new JavacTask(tb) + .options("--module-source-path", msp.toString()) + .outdir(mp) + .files(findJavaFiles(msp)) + .run() + .writeAll(); + + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + "package impl; public class Impl { }"); + + Path out = base.resolve("out"); + Files.createDirectories(out); + + List log = new JavacTask(tb) + .options("-XDrawDiagnostic", + "--module-path", mp.toString(), + "--add-modules", "ALL-MODULE-PATH") + .outdir(out) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected1 = + Arrays.asList("error: the unnamed module reads package test from both m1x and m2x", + "1 error"); + + List expected2 = + Arrays.asList("error: the unnamed module reads package test from both m2x and m1x", + "1 error"); + + if (!expected1.equals(log) && !expected2.equals(log)) { + throw new AssertionError("Unexpected output: " + log); + } + } + }