This commit is contained in:
Alan Bateman 2017-06-17 08:02:55 +01:00
commit beba252b47
11 changed files with 438 additions and 6 deletions

View file

@ -1574,8 +1574,13 @@ public class Modules extends JCTree.Visitor {
: null;
DiagnosticPosition pos = env != null ? env.tree.pos() : null;
try {
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);

View file

@ -29,6 +29,7 @@ import java.io.Closeable;
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.Matcher;
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 @@ public class Locations {
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 @@ public class Locations {
}
}
//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 {

View file

@ -2990,6 +2990,10 @@ compiler.err.package.in.other.module=\
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

View file

@ -57,11 +57,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,

View file

@ -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

View file

@ -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 {
}

View file

@ -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;
}

View file

@ -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 {
}

View file

@ -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;
}

View file

@ -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 @@ public class AutomaticModules extends ModuleTestBase {
}
}
@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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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);
}
}
}

View file

@ -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 @@ public class PackageConflictTest extends ModuleTestBase {
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<String> 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<String> expected1 =
Arrays.asList("error: the unnamed module reads package test from both m1x and m2x",
"1 error");
List<String> 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);
}
}
}