# HG changeset patch # User jlahoda # Date 1494564157 -7200 # Node ID 77a2d6c1f32116be7454ac98f8be31c1603671b6 # Parent 6ffca66728a73b3dd3042a196aa1211346132fee 8178152: Handling of incubating modules, the jdk.unsupported module and --add-exports with --release 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 diff -r 6ffca66728a7 -r 77a2d6c1f321 make/gendata/Gendata-jdk.compiler.gmk --- a/make/gendata/Gendata-jdk.compiler.gmk Thu May 11 15:12:38 2017 -0700 +++ b/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, \ )) diff -r 6ffca66728a7 -r 77a2d6c1f321 make/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 "); + } + + public static void main(String... args) throws IOException { + if (args.length < 1) { + help(); + return ; + } + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + List 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 jlObjectList = Arrays.asList("java.lang.Object"); + JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, d -> {}, options, jlObjectList, null); + task.enter(); + Elements elements = task.getElements(); + List todo = new LinkedList<>(); + Arrays.stream(args).skip(1).forEach(todo::add); + Set 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); + } + +} diff -r 6ffca66728a7 -r 77a2d6c1f321 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 May 11 15:12:38 2017 -0700 +++ b/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 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 result = computeTransitiveClosure(enabledRoot, observable); + Set result = computeTransitiveClosure(enabledRoot, rootModules, observable); result.add(syms.unnamedModule); @@ -1348,12 +1350,18 @@ return allModules == null || allModules.contains(msym); } - private Set computeTransitiveClosure(Set base, Set observable) { + private Set computeTransitiveClosure(Set base, + Set rootModules, + Set observable) { List primaryTodo = List.nil(); List 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 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 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")) { diff -r 6ffca66728a7 -r 77a2d6c1f321 src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu May 11 15:12:38 2017 -0700 +++ b/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)); diff -r 6ffca66728a7 -r 77a2d6c1f321 src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Thu May 11 15:12:38 2017 -0700 +++ b/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 getPlatformPath() { - if (Target.lookup(version) == Target.DEFAULT) { - return null; - } - List paths = new ArrayList<>(); Path file = findCtSym(); // file == ${jdk.home}/lib/ct.sym @@ -128,7 +126,21 @@ try (DirectoryStream 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 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) { diff -r 6ffca66728a7 -r 77a2d6c1f321 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 May 11 15:12:38 2017 -0700 +++ b/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 diff -r 6ffca66728a7 -r 77a2d6c1f321 test/tools/javac/diags/examples/AddExportsWithRelease.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 { +} diff -r 6ffca66728a7 -r 77a2d6c1f321 test/tools/javac/diags/examples/AddReadsWithRelease.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 { +} diff -r 6ffca66728a7 -r 77a2d6c1f321 test/tools/javac/diags/examples/PatchModuleWithRelease/PatchModuleWithRelease.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 { +} diff -r 6ffca66728a7 -r 77a2d6c1f321 test/tools/javac/diags/examples/PatchModuleWithRelease/patchmodule/java.base/java/lang/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 { +} diff -r 6ffca66728a7 -r 77a2d6c1f321 test/tools/javac/options/release/ReleaseOptionClashes.java --- a/test/tools/javac/options/release/ReleaseOptionClashes.java Thu May 11 15:12:38 2017 -0700 +++ b/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 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])); diff -r 6ffca66728a7 -r 77a2d6c1f321 test/tools/javac/options/release/ReleaseOptionUnsupported.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 log; + List 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 log; + List 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 log; + List 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 log; + List 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 log; + List 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()) }); + } +}