8178152: Handling of incubating modules, the jdk.unsupported module and --add-exports with --release <current>
Summary: --release 9 should only allow documented modules; --add-exports/--add-reads/--patch-module should not be allowed on system modules when --release 9 is used.
Reviewed-by: jjg, erikj, ihse
--- a/langtools/make/gendata/Gendata-jdk.compiler.gmk Thu May 11 15:12:38 2017 -0700
+++ b/langtools/make/gendata/Gendata-jdk.compiler.gmk Fri May 12 06:42:37 2017 +0200
@@ -25,10 +25,20 @@
include JarArchive.gmk
include JavaCompilation.gmk
+include Modules.gmk
include SetupJavaCompilers.gmk
################################################################################
+# This is needed to properly setup DOCS_MODULES.
+$(eval $(call ReadImportMetaData))
+
+# Modules that should be visible for 9 - the documented modules:
+CT_MODULES := $(DOCS_MODULES)
+
+# Get the complete module source path:
+CT_MODULESOURCEPATH := $(call GetModuleSrcPath)
+
CT_DATA_DESCRIPTION ?= $(LANGTOOLS_TOPDIR)/make/data/symbols/symbols
$(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \
@@ -41,6 +51,8 @@
ifeq ($(BOOT_JDK_MODULAR), true)
COMPILECREATESYMBOLS_ADD_EXPORTS := \
+ --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
+ --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \
--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
@@ -59,6 +71,14 @@
build-ctsym \
$(CT_DATA_DESCRIPTION) \
$(@D)
+ $(MKDIR) $(@D)/9
+ $(JAVA_SMALL) $(INTERIM_LANGTOOLS_ARGS) \
+ $(COMPILECREATESYMBOLS_ADD_EXPORTS) \
+ -classpath $(BUILDTOOLS_OUTPUTDIR)/create_symbols \
+ build.tools.symbolgenerator.TransitiveDependencies \
+ $(CT_MODULESOURCEPATH) \
+ $(CT_MODULES) \
+ >$(@D)/9/system-modules
$(TOUCH) $@
# Can't generate ct.sym directly into modules libs as the SetupJarArchive macro
@@ -66,7 +86,7 @@
$(eval $(call SetupJarArchive, CREATE_CTSYM, \
DEPENDENCIES := $(SUPPORT_OUTPUTDIR)/symbols/ct.sym-files/_the.symbols, \
SRCS := $(SUPPORT_OUTPUTDIR)/symbols/ct.sym-files, \
- SUFFIXES := .sig, \
+ SUFFIXES := .sig system-modules, \
JAR := $(SUPPORT_OUTPUTDIR)/symbols/ct.sym, \
))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * 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.symbolgenerator;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.lang.model.element.ModuleElement.RequiresDirective;
+import javax.lang.model.util.Elements;
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+
+/**
+ * Print reflexive transitive closure of the given modules along their requires transitive edges.
+ */
+public class TransitiveDependencies {
+
+ private static void help() {
+ System.err.println("java TransitiveDependencies <module-source-path> <root-modules>");
+ }
+
+ public static void main(String... args) throws IOException {
+ if (args.length < 1) {
+ help();
+ return ;
+ }
+
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ List<String> options = Arrays.asList("-source", "9",
+ "-target", "9",
+ "--system", "none",
+ "--module-source-path", args[0],
+ "--add-modules", Arrays.stream(args)
+ .skip(1)
+ .collect(Collectors.joining(",")));
+ List<String> jlObjectList = Arrays.asList("java.lang.Object");
+ JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, d -> {}, options, jlObjectList, null);
+ task.enter();
+ Elements elements = task.getElements();
+ List<String> todo = new LinkedList<>();
+ Arrays.stream(args).skip(1).forEach(todo::add);
+ Set<String> allModules = new HashSet<>();
+
+ while (!todo.isEmpty()) {
+ String current = todo.remove(0);
+
+ if (!allModules.add(current))
+ continue;
+
+ ModuleSymbol mod = (ModuleSymbol) elements.getModuleElement(current);
+
+ if (mod == null) {
+ throw new IllegalStateException("Missing: " + current);
+ }
+
+ //use the internal structure to avoid unnecesarily completing the symbol using the UsesProvidesVisitor:
+ for (RequiresDirective rd : mod.requires) {
+ if (rd.isTransitive()) {
+ todo.add(rd.getDependency().getQualifiedName().toString());
+ }
+ }
+ }
+
+ allModules.add("java.base");
+ allModules.add("jdk.unsupported");
+
+ allModules.stream()
+ .sorted()
+ .forEach(System.out::println);
+ }
+
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu May 11 15:12:38 2017 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Fri May 12 06:42:37 2017 +0200
@@ -142,6 +142,7 @@
private final ModuleFinder moduleFinder;
private final Source source;
private final boolean allowModules;
+ private final boolean allowAccessIntoSystem;
public final boolean multiModuleMode;
@@ -192,6 +193,7 @@
allowModules = source.allowModules();
Options options = Options.instance(context);
+ allowAccessIntoSystem = options.isUnset(Option.RELEASE);
lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
Collection<String> xmodules = options.keySet()
@@ -1230,7 +1232,7 @@
for (String limit : extraLimitMods) {
limitMods.add(syms.enterModule(names.fromString(limit)));
}
- observable = computeTransitiveClosure(limitMods, null);
+ observable = computeTransitiveClosure(limitMods, rootModules, null);
observable.addAll(rootModules);
if (lintOptions) {
for (ModuleSymbol msym : limitMods) {
@@ -1310,7 +1312,7 @@
}
}
- Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable);
+ Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, rootModules, observable);
result.add(syms.unnamedModule);
@@ -1348,12 +1350,18 @@
return allModules == null || allModules.contains(msym);
}
- private Set<ModuleSymbol> computeTransitiveClosure(Set<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
+ private Set<ModuleSymbol> computeTransitiveClosure(Set<? extends ModuleSymbol> base,
+ Set<? extends ModuleSymbol> rootModules,
+ Set<ModuleSymbol> observable) {
List<ModuleSymbol> primaryTodo = List.nil();
List<ModuleSymbol> secondaryTodo = List.nil();
for (ModuleSymbol ms : base) {
- primaryTodo = primaryTodo.prepend(ms);
+ if (rootModules.contains(ms)) {
+ primaryTodo = primaryTodo.prepend(ms);
+ } else {
+ secondaryTodo = secondaryTodo.prepend(ms);
+ }
}
Set<ModuleSymbol> result = new LinkedHashSet<>();
@@ -1376,12 +1384,12 @@
if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0))
continue;
current.complete();
- if (current.kind == ERR && isPrimaryTodo && warnedMissing.add(current)) {
+ if (current.kind == ERR && (isPrimaryTodo || base.contains(current)) && warnedMissing.add(current)) {
log.error(Errors.ModuleNotFound(current));
}
for (RequiresDirective rd : current.requires) {
if (rd.module == syms.java_base) continue;
- if ((rd.isTransitive() && isPrimaryTodo) || base.contains(current)) {
+ if ((rd.isTransitive() && isPrimaryTodo) || rootModules.contains(current)) {
primaryTodo = primaryTodo.prepend(rd.module);
} else {
secondaryTodo = secondaryTodo.prepend(rd.module);
@@ -1488,6 +1496,10 @@
}
}
+ if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0 &&
+ msym.patchLocation != null) {
+ log.error(Errors.PatchModuleWithRelease(msym));
+ }
}
private Set<ModuleSymbol> retrieveRequiresTransitive(ModuleSymbol msym) {
@@ -1613,6 +1625,12 @@
if (!isValidName(packageName))
continue;
+
+ if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0) {
+ log.error(Errors.AddExportsWithRelease(msym));
+ continue;
+ }
+
PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
p.modle = msym; // TODO: do we need this?
@@ -1688,6 +1706,11 @@
continue;
}
+ if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0) {
+ log.error(Errors.AddReadsWithRelease(msym));
+ continue;
+ }
+
for (String targetName : targetNames.split("[ ,]+", -1)) {
ModuleSymbol targetModule;
if (targetName.equals("ALL-UNNAMED")) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu May 11 15:12:38 2017 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Fri May 12 06:42:37 2017 +0200
@@ -300,7 +300,8 @@
Option.XBOOTCLASSPATH_PREPEND,
Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
Option.EXTDIRS, Option.DJAVA_EXT_DIRS,
- Option.SOURCE, Option.TARGET);
+ Option.SOURCE, Option.TARGET,
+ Option.SYSTEM, Option.UPGRADE_MODULE_PATH);
if (platformString != null) {
PlatformDescription platformDescription = PlatformUtils.lookupPlatformDescription(platformString);
@@ -331,7 +332,12 @@
try {
StandardJavaFileManager sfm = (StandardJavaFileManager) fm;
- sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
+ if (Source.instance(context).allowModules()) {
+ sfm.handleOption("--system", Arrays.asList("none").iterator());
+ sfm.setLocationFromPaths(StandardLocation.UPGRADE_MODULE_PATH, platformCP);
+ } else {
+ sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
+ }
} catch (IOException ex) {
log.printLines(PrefixKind.JAVAC, "msg.io");
ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Thu May 11 15:12:38 2017 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Fri May 12 06:42:37 2017 +0200
@@ -26,6 +26,8 @@
package com.sun.tools.javac.platform;
import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.Charset;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
@@ -41,6 +43,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.stream.Stream;
import javax.annotation.processing.Processor;
@@ -90,7 +93,6 @@
} catch (IOException | ProviderNotFoundException ex) {
}
}
- SUPPORTED_JAVA_PLATFORM_VERSIONS.add(targetNumericVersion(Target.DEFAULT));
}
private static String targetNumericVersion(Target target) {
@@ -108,10 +110,6 @@
@Override
public Collection<Path> getPlatformPath() {
- if (Target.lookup(version) == Target.DEFAULT) {
- return null;
- }
-
List<Path> paths = new ArrayList<>();
Path file = findCtSym();
// file == ${jdk.home}/lib/ct.sym
@@ -128,7 +126,21 @@
try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
for (Path section : dir) {
if (section.getFileName().toString().contains(version)) {
- paths.add(section);
+ Path systemModules = section.resolve("system-modules");
+
+ if (Files.isRegularFile(systemModules)) {
+ Path modules =
+ FileSystems.getFileSystem(URI.create("jrt:/"))
+ .getPath("modules");
+ try (Stream<String> lines =
+ Files.lines(systemModules, Charset.forName("UTF-8"))) {
+ lines.map(line -> modules.resolve(line))
+ .filter(mod -> Files.exists(mod))
+ .forEach(mod -> paths.add(mod));
+ }
+ } else {
+ paths.add(section);
+ }
}
}
} catch (IOException ex) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu May 11 15:12:38 2017 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri May 12 06:42:37 2017 +0200
@@ -3027,6 +3027,18 @@
compiler.err.addmods.all.module.path.invalid=\
--add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module
+# 0: symbol
+compiler.err.add.exports.with.release=\
+ exporting a package from system module {0} is not allowed with --release
+
+# 0: symbol
+compiler.err.add.reads.with.release=\
+ adding read edges for system module {0} is not allowed with --release
+
+# 0: symbol
+compiler.err.patch.module.with.release=\
+ patching system module {0} is not allowed in combination with --release
+
compiler.warn.addopens.ignored=\
--add-opens has no effect at compile time
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/AddExportsWithRelease.java Fri May 12 06:42:37 2017 +0200
@@ -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.
+ */
+
+// key: compiler.err.add.exports.with.release
+// options: --add-exports java.base/jdk.internal.misc=ALL-UNNAMED --release 9
+
+class AddExportsWithRelease {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/AddReadsWithRelease.java Fri May 12 06:42:37 2017 +0200
@@ -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.
+ */
+
+// key: compiler.err.add.reads.with.release
+// options: --add-reads java.base=java.compiler --release 9
+
+class AddReadsWithRelease {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PatchModuleWithRelease/PatchModuleWithRelease.java Fri May 12 06:42:37 2017 +0200
@@ -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.
+ */
+
+// key: compiler.err.patch.module.with.release
+// options: --release 9
+
+class PatchModuleWithRelease {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PatchModuleWithRelease/patchmodule/java.base/java/lang/Test.java Fri May 12 06:42:37 2017 +0200
@@ -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 java.lang;
+
+class Test {
+}
--- a/langtools/test/tools/javac/options/release/ReleaseOptionClashes.java Thu May 11 15:12:38 2017 -0700
+++ b/langtools/test/tools/javac/options/release/ReleaseOptionClashes.java Fri May 12 06:42:37 2017 +0200
@@ -44,17 +44,19 @@
}
void run() throws Exception {
- doRunTest("-bootclasspath", "any");
- doRunTest("-Xbootclasspath:any");
- doRunTest("-Xbootclasspath/a:any");
- doRunTest("-Xbootclasspath/p:any");
- doRunTest("-endorseddirs", "any");
- doRunTest("-extdirs", "any");
- doRunTest("-source", "8");
- doRunTest("-target", "8");
+ doRunTest("7", "-bootclasspath", "any");
+ doRunTest("7", "-Xbootclasspath:any");
+ doRunTest("7", "-Xbootclasspath/a:any");
+ doRunTest("7", "-Xbootclasspath/p:any");
+ doRunTest("7", "-endorseddirs", "any");
+ doRunTest("7", "-extdirs", "any");
+ doRunTest("7", "-source", "8");
+ doRunTest("7", "-target", "8");
+ doRunTest("9", "--system", "none");
+ doRunTest("9", "--upgrade-module-path", "any");
}
- void doRunTest(String... args) throws Exception {
+ void doRunTest(String release, String... args) throws Exception {
System.out.println("Testing clashes for arguments: " + Arrays.asList(args));
Class<?> log = Class.forName("com.sun.tools.javac.util.Log", true, cl);
Field useRawMessages = log.getDeclaredField("useRawMessages");
@@ -62,7 +64,7 @@
useRawMessages.setBoolean(null, true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
List<String> options = new ArrayList<>();
- options.addAll(Arrays.asList("--release", "7"));
+ options.addAll(Arrays.asList("--release", release));
options.addAll(Arrays.asList(args));
options.add(System.getProperty("test.src") + File.separator + "ReleaseOptionClashes.java");
compiler.run(null, null, out, options.toArray(new String[0]));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/options/release/ReleaseOptionUnsupported.java Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,313 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8178152
+ * @summary Verify unsupported modules and module options handling.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.jvm
+ * jdk.jdeps/com.sun.tools.classfile
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask toolbox.TestRunner
+ * @run main ReleaseOptionUnsupported
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import com.sun.tools.javac.jvm.Target;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class ReleaseOptionUnsupported extends TestRunner {
+
+ private final ToolBox tb = new ToolBox();
+
+ public ReleaseOptionUnsupported() {
+ super(System.err);
+ }
+
+ public static void main(String... args) throws Exception {
+ new ReleaseOptionUnsupported().runTests();
+ }
+
+ @Test
+ public void testUnsafe(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module m { requires jdk.unsupported; }",
+ "package test; public class Test { sun.misc.Unsafe unsafe; } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List<String> log;
+ List<String> expected = Arrays.asList(
+ "Test.java:1:43: compiler.warn.sun.proprietary: sun.misc.Unsafe",
+ "1 warning"
+ );
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+ }
+
+ @Test
+ public void testUnsafeUnnamed(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package test; public class Test { sun.misc.Unsafe unsafe; } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List<String> log;
+ List<String> expected = Arrays.asList(
+ "Test.java:1:43: compiler.warn.sun.proprietary: sun.misc.Unsafe",
+ "1 warning"
+ );
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+ }
+
+ @Test
+ public void testAddExports(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module m { }",
+ "package test; public class Test { jdk.internal.misc.Unsafe unsafe; } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--add-exports", "java.base/jdk.internal.misc=m")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> log;
+ List<String> expected;
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--add-exports", "java.base/jdk.internal.misc=m",
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ expected = Arrays.asList(
+ "- compiler.err.add.exports.with.release: java.base",
+ "1 error"
+ );
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ //OK to add exports a package of a non-system module:
+ tb.writeJavaFiles(src,
+ "package test; public class Test { } ");
+ tb.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--add-exports", "m/test=ALL-UNNAMED",
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+ }
+
+ @Test
+ public void testAddReads(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module m { }",
+ "package test; public class Test { } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--add-reads", "java.base=m")
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> log;
+ List<String> expected;
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--add-reads", "java.base=m",
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ expected = Arrays.asList(
+ "- compiler.err.add.reads.with.release: java.base",
+ "1 error"
+ );
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ //OK to add reads a package of a non-system module:
+ tb.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--add-reads", "m=java.base",
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+ }
+
+ @Test
+ public void testPatchModule(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module m { }",
+ "package test; public class Test { } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+ Path patch = base.resolve("patch");
+ tb.createDirectories(patch);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--patch-module", "java.base=" + patch)
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> log;
+ List<String> expected;
+
+ log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--patch-module", "java.base=" + patch,
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ expected = Arrays.asList(
+ "- compiler.err.patch.module.with.release: java.base",
+ "1 error"
+ );
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Unexpected output: " + log);
+ }
+
+ //OK to patch a non-system module:
+ tb.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "--patch-module", "m=" + patch,
+ "--release", Target.DEFAULT.multiReleaseValue())
+ .outdir(classes)
+ .files(tb.findJavaFiles(src))
+ .run(Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+ }
+
+ protected void runTests() throws Exception {
+ runTests(m -> new Object[] { Paths.get(m.getName()) });
+ }
+}