1 /*
2  * Copyright (c) 2016, 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  * @summary tests for module resolution
27  * @library /tools/lib
28  * @modules
29  *      jdk.compiler/com.sun.tools.javac.api
30  *      jdk.compiler/com.sun.tools.javac.main
31  * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
32  * @run main QueryBeforeEnter
33  */
34 
35 import java.io.File;
36 import java.io.OutputStream;
37 import java.nio.file.*;
38 import java.util.Arrays;
39 import java.util.Set;
40 
41 import javax.annotation.processing.AbstractProcessor;
42 import javax.annotation.processing.RoundEnvironment;
43 import javax.annotation.processing.SupportedAnnotationTypes;
44 import javax.annotation.processing.SupportedSourceVersion;
45 import javax.lang.model.SourceVersion;
46 import javax.lang.model.element.TypeElement;
47 import javax.tools.JavaCompiler;
48 import javax.tools.StandardJavaFileManager;
49 import javax.tools.ToolProvider;
50 
51 // import com.sun.source.util.JavacTask;
52 import com.sun.source.util.Plugin;
53 import com.sun.source.util.TaskEvent;
54 import com.sun.source.util.TaskListener;
55 import com.sun.tools.javac.Main;
56 
57 import toolbox.JavacTask;
58 import toolbox.Task;
59 import toolbox.ToolBox;
60 
61 public class QueryBeforeEnter extends ModuleTestBase {
main(String... args)62     public static void main(String... args) throws Exception {
63         QueryBeforeEnter t = new QueryBeforeEnter();
64         t.runTests();
65     }
66 
67     @Test
testEmpty(Path base)68     public void testEmpty(Path base) throws Exception {
69         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
70         com.sun.source.util.JavacTask task =
71             (com.sun.source.util.JavacTask) javaCompiler.getTask(null, null, null, null, null, null);
72         TypeElement jlString = task.getElements().getTypeElement("java.lang.String");
73 
74         assertNotNull(jlString);
75     }
76 
77     @Test
testUnnamed(Path base)78     public void testUnnamed(Path base) throws Exception {
79         Path moduleSrc = base.resolve("module-src");
80         Path m1 = moduleSrc.resolve("m1x");
81 
82         tb.writeJavaFiles(m1,
83                           "module m1x { exports m1x; }",
84                           "package m1x; public class M1 {}");
85 
86         Path m2 = moduleSrc.resolve("m2x");
87 
88         tb.writeJavaFiles(m2,
89                           "module m2x { exports m2x; }",
90                           "package m2x; public class M2 {}");
91 
92         Path modulePath = base.resolve("module-path");
93 
94         Files.createDirectories(modulePath);
95 
96         new JavacTask(tb)
97                 .options("--module-source-path", moduleSrc.toString())
98                 .outdir(modulePath)
99                 .files(findJavaFiles(moduleSrc))
100                 .run()
101                 .writeAll();
102 
103         Path cpSrc = base.resolve("cp-src");
104 
105         tb.writeJavaFiles(cpSrc,
106                           "package cp; public class CP {}");
107 
108         Path cp = base.resolve("cp");
109 
110         Files.createDirectories(cp);
111 
112         new JavacTask(tb)
113                 .outdir(cp)
114                 .files(findJavaFiles(cpSrc))
115                 .run()
116                 .writeAll();
117 
118         Path src = base.resolve("src");
119 
120         tb.writeJavaFiles(src,
121                           "package test; public class Test1 {}",
122                           "package test; public class Test2 {}");
123 
124         Path out = base.resolve("out");
125 
126         Files.createDirectories(out);
127 
128         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
129         try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
130             com.sun.source.util.JavacTask task =
131                 (com.sun.source.util.JavacTask) javaCompiler.getTask(null,
132                                                               null,
133                                                               d -> { throw new IllegalStateException(d.toString()); },
134                                                               Arrays.asList("--module-path", modulePath.toString(),
135                                                                             "--class-path", cp.toString(),
136                                                                             "-sourcepath", src.toString()),
137                                                               null,
138                                                               fm.getJavaFileObjects(src.resolve("test").resolve("Test2.java")));
139             assertNotNull(task.getElements().getTypeElement("java.lang.String"));
140             assertNotNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
141             assertNull(task.getElements().getTypeElement("m1x.M1"));
142             assertNull(task.getElements().getTypeElement("m2x.M2"));
143             assertNotNull(task.getElements().getTypeElement("cp.CP"));
144             assertNotNull(task.getElements().getTypeElement("test.Test1"));
145             assertNotNull(task.getElements().getTypeElement("test.Test2"));
146             assertNotNull(task.getElements().getModuleElement("java.base"));
147             assertNotNull(task.getElements().getModuleElement("java.compiler"));
148             assertNull(task.getElements().getModuleElement("m1x"));
149             assertNull(task.getElements().getModuleElement("m2x"));
150         }
151     }
152 
153     @Test
testSingleNamed(Path base)154     public void testSingleNamed(Path base) throws Exception {
155         Path moduleSrc = base.resolve("module-src");
156         Path m1 = moduleSrc.resolve("m1x");
157 
158         tb.writeJavaFiles(m1,
159                           "module m1x { exports m1x; }",
160                           "package m1x; public class M1 {}");
161 
162         Path m2 = moduleSrc.resolve("m2x");
163 
164         tb.writeJavaFiles(m2,
165                           "module m2x { exports m2x; }",
166                           "package m2x; public class M2 {}");
167 
168         Path modulePath = base.resolve("module-path");
169 
170         Files.createDirectories(modulePath);
171 
172         new JavacTask(tb)
173                 .options("--module-source-path", moduleSrc.toString())
174                 .outdir(modulePath)
175                 .files(findJavaFiles(moduleSrc))
176                 .run()
177                 .writeAll();
178 
179         Path cpSrc = base.resolve("cp-src");
180 
181         tb.writeJavaFiles(cpSrc,
182                           "package cp; public class CP {}");
183 
184         Path cp = base.resolve("cp");
185 
186         Files.createDirectories(cp);
187 
188         new JavacTask(tb)
189                 .outdir(cp)
190                 .files(findJavaFiles(cpSrc))
191                 .run()
192                 .writeAll();
193 
194         Path src = base.resolve("src");
195 
196         tb.writeJavaFiles(src,
197                           "module test { requires java.base; requires m1x; } ",
198                           "package test; public class Test {}");
199 
200         Path out = base.resolve("out");
201 
202         Files.createDirectories(out);
203 
204         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
205         try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
206             com.sun.source.util.JavacTask task =
207                 (com.sun.source.util.JavacTask) javaCompiler.getTask(null,
208                                                               null,
209                                                               d -> { throw new IllegalStateException(d.toString()); },
210                                                               Arrays.asList("--module-path", modulePath.toString(),
211                                                                             "--class-path", cp.toString(),
212                                                                             "-sourcepath", src.toString()),
213                                                               null,
214                                                               fm.getJavaFileObjects(findJavaFiles(src)));
215             assertNotNull(task.getElements().getTypeElement("java.lang.String"));
216             assertNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
217             assertNotNull(task.getElements().getTypeElement("m1x.M1"));
218             assertNull(task.getElements().getTypeElement("m2x.M2"));
219             assertNotNull(task.getElements().getTypeElement("test.Test"));
220             assertNotNull(task.getElements().getModuleElement("java.base"));
221             assertNull(task.getElements().getModuleElement("java.compiler"));
222             assertNotNull(task.getElements().getModuleElement("m1x"));
223             assertNull(task.getElements().getModuleElement("m2x"));
224             assertNotNull(task.getElements().getModuleElement("test"));
225         }
226     }
227 
228     @Test
testMultiModule(Path base)229     public void testMultiModule(Path base) throws Exception {
230         Path modulePathSrc = base.resolve("module-path-src");
231         Path m1 = modulePathSrc.resolve("m1x");
232 
233         tb.writeJavaFiles(m1,
234                           "module m1x { exports m1x; }",
235                           "package m1x; public class M1 {}");
236 
237         Path m2 = modulePathSrc.resolve("m2x");
238 
239         tb.writeJavaFiles(m2,
240                           "module m2x { exports m2x; }",
241                           "package m2x; public class M2 {}");
242 
243         Path modulePath = base.resolve("module-path");
244 
245         Files.createDirectories(modulePath);
246 
247         new JavacTask(tb)
248                 .options("--module-source-path", modulePathSrc.toString())
249                 .outdir(modulePath)
250                 .files(findJavaFiles(modulePathSrc))
251                 .run()
252                 .writeAll();
253 
254         Path cpSrc = base.resolve("cp-src");
255 
256         tb.writeJavaFiles(cpSrc,
257                           "package cp; public class CP {}");
258 
259         Path cp = base.resolve("cp");
260 
261         Files.createDirectories(cp);
262 
263         new JavacTask(tb)
264                 .outdir(cp)
265                 .files(findJavaFiles(cpSrc))
266                 .run()
267                 .writeAll();
268 
269         Path moduleSrc = base.resolve("module-src");
270         Path m3 = moduleSrc.resolve("m3x");
271 
272         tb.writeJavaFiles(m3,
273                           "module m3x { requires m1x; exports m3x; }",
274                           "package m3x; public class M3 {  }");
275 
276         Path m4 = moduleSrc.resolve("m4x");
277 
278         tb.writeJavaFiles(m4,
279                           "module m4x { exports m4x; }",
280                           "package m4x; public class M4 {}");
281 
282         Path out = base.resolve("out");
283 
284         Files.createDirectories(out);
285 
286         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
287         try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
288             com.sun.source.util.JavacTask task =
289                 (com.sun.source.util.JavacTask) javaCompiler.getTask(null,
290                                                               null,
291                                                               d -> { throw new IllegalStateException(d.toString()); },
292                                                               Arrays.asList("--module-path", modulePath.toString(),
293                                                                             "--class-path", cp.toString(),
294                                                                             "--module-source-path", moduleSrc.toString(),
295                                                                             "-d", out.toString()),
296                                                               null,
297                                                               fm.getJavaFileObjects(findJavaFiles(moduleSrc)));
298             assertNotNull(task.getElements().getTypeElement("java.lang.String"));
299             assertNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
300             assertNotNull(task.getElements().getTypeElement("m1x.M1"));
301             assertNull(task.getElements().getTypeElement("m2x.M2"));
302             assertNotNull(task.getElements().getTypeElement("m3x.M3"));
303             assertNotNull(task.getElements().getTypeElement("m4x.M4"));
304             assertNotNull(task.getElements().getModuleElement("java.base"));
305             assertNull(task.getElements().getModuleElement("java.compiler"));
306             assertNotNull(task.getElements().getModuleElement("m1x"));
307             assertNull(task.getElements().getModuleElement("m2x"));
308             assertNotNull(task.getElements().getModuleElement("m3x"));
309             assertNotNull(task.getElements().getModuleElement("m4x"));
310         }
311     }
312 
313     @Test
testTooSoon(Path base)314     public void testTooSoon(Path base) throws Exception {
315         Path src = base.resolve("src");
316 
317         tb.writeJavaFiles(src,
318                           "package test; public class Test {}");
319 
320         Path out = base.resolve("out");
321 
322         Files.createDirectories(out);
323 
324         Path reg = base.resolve("reg");
325         Path regFile = reg.resolve("META-INF").resolve("services").resolve(Plugin.class.getName());
326 
327         Files.createDirectories(regFile.getParent());
328 
329         try (OutputStream regOut = Files.newOutputStream(regFile)) {
330             regOut.write(PluginImpl.class.getName().getBytes());
331         }
332 
333         String processorPath = System.getProperty("test.class.path") + File.pathSeparator + reg.toString();
334 
335         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
336         Path testSource = src.resolve("test").resolve("Test.java");
337         try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
338             com.sun.source.util.JavacTask task =
339                 (com.sun.source.util.JavacTask) javaCompiler.getTask(null,
340                                                               null,
341                                                               d -> { throw new IllegalStateException(d.toString()); },
342                                                               Arrays.asList("--processor-path", processorPath,
343                                                                             "-processor", AP.class.getName(),
344                                                                             "-Xplugin:test"),
345                                                               null,
346                                                               fm.getJavaFileObjects(testSource));
347             task.call();
348         }
349 
350         Main.compile(new String[] {"--processor-path", processorPath,
351                                    "-Xplugin:test",
352                                    testSource.toString()});
353     }
354 
355     public static class PluginImpl implements Plugin {
356 
357         @Override
getName()358         public String getName() {
359             return "test";
360         }
361 
362         @Override
init(com.sun.source.util.JavacTask task, String... args)363         public void init(com.sun.source.util.JavacTask task, String... args) {
364             task.addTaskListener(new TaskListener() {
365                 boolean wasEntered;
366                 @Override
367                 public void started(TaskEvent e) {
368                     switch (e.getKind()) {
369                         case COMPILATION: case PARSE:
370                             shouldFail(e.getKind());
371                             break;
372                         case ANNOTATION_PROCESSING: case ENTER:
373                             if (wasEntered) {
374                                 shouldPass(e.getKind());
375                             } else {
376                                 shouldFail(e.getKind());
377                             }
378                             break;
379                         default:
380                             shouldPass(e.getKind());
381                             break;
382                     }
383                 }
384                 @Override
385                 public void finished(TaskEvent e) {
386                     switch (e.getKind()) {
387                         case PARSE:
388                             shouldFail(e.getKind());
389                             break;
390                         case ENTER:
391                             wasEntered = true;
392                             //fall-through:
393                         default:
394                             shouldPass(e.getKind());
395                             break;
396                     }
397                 }
398                 private void shouldFail(TaskEvent.Kind kind) {
399                     try {
400                         task.getElements().getTypeElement("java.lang.String");
401                         throw new AssertionError("Expected exception not observed; kind=" + kind.name());
402                     } catch (IllegalStateException ex) {
403                         //correct
404                     }
405                 }
406                 private void shouldPass(TaskEvent.Kind kind) {
407                     assertNotNull(task.getElements().getTypeElement("java.lang.String"));
408                 }
409             });
410 
411         }
412 
413     }
414 
415     @SupportedAnnotationTypes("*")
416     public static final class AP extends AbstractProcessor {
417 
418         @Override
process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)419         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
420             return false;
421         }
422 
423         @Override
getSupportedSourceVersion()424         public SourceVersion getSupportedSourceVersion() {
425             return SourceVersion.latest();
426         }
427 
428     }
429 
assertNotNull(Object actual)430     private static void assertNotNull(Object actual) {
431         if (actual == null) {
432             throw new AssertionError("unexpected null!");
433         }
434     }
435 
assertNull(Object actual)436     private static void assertNull(Object actual) {
437         if (actual != null) {
438             throw new AssertionError("unexpected non null!");
439         }
440     }
441 
442 }
443