1 /*
   2  * Copyright (c) 2018, 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 8207954
  27  * @summary Verify that CreateSymbols can handle classfiles from the current release.
  28  * @library /tools/lib /tools/javac/lib
  29  * @modules jdk.compiler/com.sun.tools.javac.api:+open
  30  *          jdk.compiler/com.sun.tools.javac.main
  31  *          jdk.compiler/com.sun.tools.javac.jvm:+open
  32  *          jdk.compiler/com.sun.tools.javac.util:+open
  33  *          jdk.jdeps/com.sun.tools.classfile:+open
  34  * @build toolbox.ToolBox toolbox.JavacTask toolbox.Task
  35  * @run main CanHandleClassFilesTest
  36  */
  37 
  38 import java.io.Writer;
  39 import java.nio.file.Files;
  40 import java.nio.file.Path;
  41 import java.nio.file.Paths;
  42 import java.util.stream.Stream;
  43 
  44 import javax.tools.StandardLocation;
  45 
  46 import toolbox.JavacTask;
  47 import toolbox.ToolBox;
  48 
  49 public class CanHandleClassFilesTest {
  50 
  51     public static void main(String... args) throws Exception {
  52         new CanHandleClassFilesTest().run();
  53     }
  54 
  55     void run() throws Exception {
  56         var testSrc = Paths.get(System.getProperty("test.src", "."));
  57         var targetDir = Paths.get(".");
  58         Path createSymbols = null;
  59         Path includeList = null;
  60         for (Path d = testSrc; d != null; d = d.getParent()) {
  61             if (Files.exists(d.resolve("TEST.ROOT"))) {
  62                 d = d.getParent().getParent();
  63                 Path test = d.resolve("make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java");
  64                 if (Files.exists(test)) {
  65                     createSymbols = test;
  66                     includeList = d.resolve("make/data/symbols/include.list");
  67                     break;
  68                 }
  69             }
  70         }
  71         if (createSymbols == null || includeList == null || !Files.isReadable(includeList)) {
  72             System.err.println("Warning: sources not found, test skipped.");
  73             return ;
  74         }
  75         try (ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager()) {
  76             ToolBox tb = new ToolBox();
  77             new JavacTask(tb)
  78               .options("--add-exports", "jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED",
  79                        "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
  80                        "--add-exports", "jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED",
  81                        "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
  82                        "--add-modules", "jdk.jdeps")
  83               .files(createSymbols)
  84               .fileManager(mfm)
  85               .run()
  86               .writeAll();
  87 
  88             ClassLoader cl = new ClassLoader() {
  89                 @Override
  90                 protected Class<?> findClass(String name) throws ClassNotFoundException {
  91                     byte[] data = mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, name);
  92                     if (data != null) {
  93                         return defineClass(name, data, 0, data.length);
  94                     } else {
  95                         throw new ClassNotFoundException(name);
  96                     }
  97                 }
  98             };
  99 
 100             // open the non-exported packages needed by CreateSymbols to its module
 101             Module targetModule = cl.getUnnamedModule();
 102             Stream.of("jdk.compiler/com.sun.tools.javac.api",
 103                       "jdk.compiler/com.sun.tools.javac.jvm",
 104                       "jdk.compiler/com.sun.tools.javac.util",
 105                       "jdk.jdeps/com.sun.tools.classfile")
 106                     .forEach(p -> open(p, targetModule));
 107 
 108             var createSymbolsClass = Class.forName("build.tools.symbolgenerator.CreateSymbols", false, cl);
 109             var main = createSymbolsClass.getMethod("main", String[].class);
 110             var symbols = targetDir.resolve("symbols");
 111 
 112             try (Writer w = Files.newBufferedWriter(symbols)) {}
 113 
 114             main.invoke(null,
 115                         (Object) new String[] {"build-description-incremental",
 116                                                symbols.toAbsolutePath().toString(),
 117                                                includeList.toAbsolutePath().toString()});
 118 
 119             main.invoke(null,
 120                         (Object) new String[] {"build-ctsym",
 121                                                "does-not-exist",
 122                                                symbols.toAbsolutePath().toString(),
 123                                                targetDir.resolve("ct.sym").toAbsolutePath().toString()});
 124         }
 125     }
 126 
 127     void open(String moduleAndPackage, Module target) {
 128         String[] s = moduleAndPackage.split("/");
 129         var moduleName = s[0];
 130         var packageName = s[1];
 131         ModuleLayer.boot().findModule(moduleName).orElseThrow().addOpens(packageName, target);
 132     }
 133 
 134 }