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 {
  62     public static void main(String... args) throws Exception {
  63         QueryBeforeEnter t = new QueryBeforeEnter();
  64         t.runTests();
  65     }
  66 
  67     @Test
  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
  78     public void testUnnamed(Path base) throws Exception {
  79         Path moduleSrc = base.resolve("module-src");
  80         Path m1 = moduleSrc.resolve("m1");
  81 
  82         tb.writeJavaFiles(m1,
  83                           "module m1 { exports m1; }",
  84                           "package m1; public class M1 {}");
  85 
  86         Path m2 = moduleSrc.resolve("m2");
  87 
  88         tb.writeJavaFiles(m2,
  89                           "module m2 { exports m2; }",
  90                           "package m2; public class M2 {}");
  91 
  92         Path modulePath = base.resolve("module-path");
  93 
  94         Files.createDirectories(modulePath);
  95 
  96         new JavacTask(tb)
  97                 .options("-modulesourcepath", 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("-modulepath", modulePath.toString(),
 135                                                                             "-classpath", 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("m1.M1"));
 142             assertNull(task.getElements().getTypeElement("m2.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("m1"));
 149             assertNull(task.getElements().getModuleElement("m2"));
 150         }
 151     }
 152 
 153     @Test
 154     public void testSingleNamed(Path base) throws Exception {
 155         Path moduleSrc = base.resolve("module-src");
 156         Path m1 = moduleSrc.resolve("m1");
 157 
 158         tb.writeJavaFiles(m1,
 159                           "module m1 { exports m1; }",
 160                           "package m1; public class M1 {}");
 161 
 162         Path m2 = moduleSrc.resolve("m2");
 163 
 164         tb.writeJavaFiles(m2,
 165                           "module m2 { exports m2; }",
 166                           "package m2; public class M2 {}");
 167 
 168         Path modulePath = base.resolve("module-path");
 169 
 170         Files.createDirectories(modulePath);
 171 
 172         new JavacTask(tb)
 173                 .options("-modulesourcepath", 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 m1; } ",
 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("-modulepath", modulePath.toString(),
 211                                                                             "-classpath", 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("m1.M1"));
 218             assertNull(task.getElements().getTypeElement("m2.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("m1"));
 223             assertNull(task.getElements().getModuleElement("m2"));
 224             assertNotNull(task.getElements().getModuleElement("test"));
 225         }
 226     }
 227 
 228     @Test
 229     public void testMultiModule(Path base) throws Exception {
 230         Path modulePathSrc = base.resolve("module-path-src");
 231         Path m1 = modulePathSrc.resolve("m1");
 232 
 233         tb.writeJavaFiles(m1,
 234                           "module m1 { exports m1; }",
 235                           "package m1; public class M1 {}");
 236 
 237         Path m2 = modulePathSrc.resolve("m2");
 238 
 239         tb.writeJavaFiles(m2,
 240                           "module m2 { exports m2; }",
 241                           "package m2; public class M2 {}");
 242 
 243         Path modulePath = base.resolve("module-path");
 244 
 245         Files.createDirectories(modulePath);
 246 
 247         new JavacTask(tb)
 248                 .options("-modulesourcepath", 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("m3");
 271 
 272         tb.writeJavaFiles(m3,
 273                           "module m3 { requires m1; exports m3; }",
 274                           "package m3; public class M3 {  }");
 275 
 276         Path m4 = moduleSrc.resolve("m4");
 277 
 278         tb.writeJavaFiles(m4,
 279                           "module m4 { exports m4; }",
 280                           "package m4; 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("-modulepath", modulePath.toString(),
 293                                                                             "-classpath", cp.toString(),
 294                                                                             "-modulesourcepath", 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("m1.M1"));
 301             assertNull(task.getElements().getTypeElement("m2.M2"));
 302             assertNotNull(task.getElements().getTypeElement("m3.M3"));
 303             assertNotNull(task.getElements().getTypeElement("m4.M4"));
 304             assertNotNull(task.getElements().getModuleElement("java.base"));
 305             assertNull(task.getElements().getModuleElement("java.compiler"));
 306             assertNotNull(task.getElements().getModuleElement("m1"));
 307             assertNull(task.getElements().getModuleElement("m2"));
 308             assertNotNull(task.getElements().getModuleElement("m3"));
 309             assertNotNull(task.getElements().getModuleElement("m4"));
 310         }
 311     }
 312 
 313     @Test
 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("-processorpath", 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[] {"-processorpath", processorPath,
 351                                    "-Xplugin:test",
 352                                    testSource.toString()});
 353     }
 354 
 355     public static class PluginImpl implements Plugin {
 356 
 357         @Override
 358         public String getName() {
 359             return "test";
 360         }
 361 
 362         @Override
 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
 419         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
 420             return false;
 421         }
 422 
 423         @Override
 424         public SourceVersion getSupportedSourceVersion() {
 425             return SourceVersion.latest();
 426         }
 427 
 428     }
 429 
 430     private static void assertNotNull(Object actual) {
 431         if (actual == null) {
 432             throw new AssertionError("unexpected null!");
 433         }
 434     }
 435 
 436     private static void assertNull(Object actual) {
 437         if (actual != null) {
 438             throw new AssertionError("unexpected non null!");
 439         }
 440     }
 441 
 442 }