1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8235597 27 * @summary Extend support for -XDaccessInternalAPI to plugin modules 28 * @library /tools/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.code 31 * jdk.compiler/com.sun.tools.javac.main 32 * jdk.jlink 33 * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask 34 * @run main InternalAPI 35 */ 36 37 import java.io.IOException; 38 import java.util.List; 39 import java.nio.file.Files; 40 import java.nio.file.Path; 41 import java.util.spi.ToolProvider; 42 43 import toolbox.ExecTask; 44 import toolbox.JarTask; 45 import toolbox.JavacTask; 46 import toolbox.Task; 47 import toolbox.TestRunner; 48 import toolbox.ToolBox; 49 50 public class InternalAPI extends TestRunner { main(String... args)51 public static void main(String... args) throws Exception { 52 new InternalAPI().run(); 53 } 54 InternalAPI()55 InternalAPI() { 56 super(System.out); 57 } 58 59 ToolBox tb = new ToolBox(); 60 61 Path pluginJar; 62 Path mclasses; 63 run()64 void run() throws Exception { 65 Path src = Path.of("src"); 66 tb.writeJavaFiles(src, 67 "package p;\n" 68 + "import javax.lang.model.element.*;\n" 69 + "import com.sun.source.util.*;\n" 70 + "import com.sun.tools.javac.code.Symbol.ClassSymbol;\n" 71 + "public class C implements Plugin, TaskListener {\n" 72 + " public String getName() { return \"TestPlugin\"; }\n" 73 + " public boolean autoStart() { return true; }\n" 74 + " public void init(JavacTask task, String... args) {\n" 75 + " System.out.println(\"C.init \" + java.util.Arrays.toString(args));\n" 76 + " task.addTaskListener(this);\n" 77 + " }\n" 78 + " public void started(TaskEvent e) {\n" 79 + " TypeElement te = e.getTypeElement();\n" 80 + " if (te != null) {\n" 81 + " ClassSymbol sym = (ClassSymbol) te;\n" 82 + " System.out.println(e.getKind() + \" \" + te + \" \" + sym.kind);\n" 83 + " }\n" 84 + " }\n" 85 + "}\n"); 86 87 Path msrc = Path.of("msrc"); 88 tb.writeJavaFiles(msrc, 89 "module m {\n" 90 + " requires jdk.compiler;\n" 91 + " provides com.sun.source.util.Plugin with p.C;\n" 92 + "}\n"); 93 94 Path classes = Files.createDirectories(Path.of("classes")); 95 new JavacTask(tb) 96 .outdir(classes) 97 .options("--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED") 98 .files(tb.findJavaFiles(src)) 99 .run() 100 .writeAll(); 101 102 tb.writeFile(classes.resolve("META-INF").resolve("services").resolve("com.sun.source.util.Plugin"), 103 "p.C\n"); 104 105 pluginJar = Path.of("plugin.jar"); 106 new JarTask(tb, pluginJar) 107 .baseDir(classes) 108 .files(".") 109 .run(); 110 111 mclasses = Files.createDirectories(Path.of("mclasses")); 112 new JavacTask(tb) 113 .outdir(mclasses) 114 .sourcepath(msrc, src) 115 .options("--add-exports", "jdk.compiler/com.sun.tools.javac.code=m") 116 .files(tb.findJavaFiles(msrc)) 117 .run() 118 .writeAll(); 119 120 Path hw = Path.of("hw"); 121 tb.writeJavaFiles(hw, 122 "public class HelloWorld {\n" 123 + " public static void main(String... args) {\n" 124 + " System.out.println(\"Hello World!\");\n" 125 + " }\n" 126 + "}\n"); 127 128 runTests(m -> new Object[] { Path.of(m.getName()) }); 129 } 130 131 @Test testClassPath(Path base)132 public void testClassPath(Path base) throws Exception { 133 List<String> stdout = new JavacTask(tb) 134 .options("-XDaccessInternalAPI") 135 .classpath(pluginJar) 136 .outdir(Files.createDirectories(base.resolve("out"))) 137 .files(tb.findJavaFiles(Path.of("hw"))) 138 .run() 139 .writeAll() 140 .getOutputLines(Task.OutputKind.STDOUT); 141 tb.checkEqual(stdout, List.of("C.init []", "ANALYZE HelloWorld TYP", "GENERATE HelloWorld TYP")); 142 } 143 144 // negative control test: access fails without the new option 145 @Test testModuleControl(Path base)146 public void testModuleControl(Path base) throws Exception { 147 try { 148 new JavacTask(tb) 149 .options("--processor-module-path", mclasses.toString()) 150 .outdir(Files.createDirectories(base.resolve("out"))) 151 .files(tb.findJavaFiles(Path.of("hw"))) 152 .run() 153 .writeAll(); 154 throw new Exception("expected exception not thrown"); 155 } catch (Exception e) { 156 System.out.println("*** " + e); 157 String msg = e.getMessage(); 158 if (!msg.contains("java.lang.IllegalAccessError: class p.C (in module m) " 159 + "cannot access class com.sun.tools.javac.code.Symbol$ClassSymbol (in module jdk.compiler)")) { 160 throw new Exception("expected exception not found"); 161 } 162 } 163 } 164 165 // positive test: access succeeds with option for modules on modulepath 166 @Test testModulePath(Path base)167 public void testModulePath(Path base) throws IOException { 168 List<String> stdout = new JavacTask(tb) 169 .options("--processor-module-path", mclasses.toString(), 170 "-XDaccessInternalAPI") 171 .outdir(Files.createDirectories(base.resolve("out"))) 172 .files(tb.findJavaFiles(Path.of("hw"))) 173 .run() 174 .writeAll() 175 .getOutputLines(Task.OutputKind.STDOUT); 176 tb.checkEqual(stdout, List.of("C.init []", "ANALYZE HelloWorld TYP", "GENERATE HelloWorld TYP")); 177 } 178 179 // positive test: access succeeds with option for modules in image 180 @Test testImage(Path base)181 public void testImage(Path base) throws Exception { 182 Path tmpJDK = base.resolve("tmpJDK"); 183 ToolProvider jlink = ToolProvider.findFirst("jlink") 184 .orElseThrow(() -> new Exception("cannot find jlink")); 185 jlink.run(System.out, System.err, 186 "--module-path", mclasses.toString(), 187 "--add-modules", "jdk.compiler,jdk.zipfs,m", 188 "--output", tmpJDK.toString()); 189 190 String suffix = tb.isWindows() ? ".exe" : ""; 191 List<String> stdout = new ExecTask(tb, tmpJDK.resolve("bin").resolve("javac" + suffix)) 192 .args("-d", Files.createDirectories(base.resolve("out")).toString(), 193 "-XDaccessInternalAPI", 194 Path.of("hw").resolve("HelloWorld.java").toString()) 195 .run() 196 .writeAll() 197 .getOutputLines(Task.OutputKind.STDOUT); 198 tb.checkEqual(stdout, List.of("C.init []", "ANALYZE HelloWorld TYP", "GENERATE HelloWorld TYP")); 199 } 200 } 201 202