/* * Copyright (c) 2015, 2016, 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 8054717 * @summary Make sure extraction of non-private APIs work as expected. * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.sjavac * jdk.compiler/com.sun.tools.sjavac.options * jdk.compiler/com.sun.tools.sjavac.pubapi * @build Wrapper toolbox.ToolBox toolbox.JavacTask * @run main Wrapper ApiExtraction */ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PROTECTED; import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.lang.model.type.TypeKind; import com.sun.tools.sjavac.PubApiExtractor; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PrimitiveTypeDesc; import com.sun.tools.sjavac.pubapi.PubApi; import com.sun.tools.sjavac.pubapi.PubMethod; import com.sun.tools.sjavac.pubapi.PubType; import com.sun.tools.sjavac.pubapi.PubVar; import com.sun.tools.sjavac.pubapi.ReferenceTypeDesc; import toolbox.JavacTask; import toolbox.ToolBox; public class ApiExtraction { public static void main(String[] args) throws IOException { String testSrc = String.join("\n", "import java.util.*;", "public final class TestClass extends Thread {", // Fields with various combination of modifiers " private String s1 = \"str 1\";", " public String s2 = \"str 2\";", " protected final String s3 = \"str 3\";", " static String s4 = \"str 4\";", // Methods with various combinations of types and modifiers " protected void m1() {}", " public static Map> m2() {", " return null;", " }", " final void m3(Set>> s) {}", // Some inner classes " static class DummyInner1 implements Runnable {", " protected int field;", " public void run() {}", " }", " final class DummyInner2 { }", "}"); // Create class file to extract API from new JavacTask(new ToolBox()).sources(testSrc).run(); // Extract PubApi Options options = Options.parseArgs("-d", "bin", "--state-dir=bin", "-cp", "."); PubApiExtractor pubApiExtr = new PubApiExtractor(options); PubApi actualApi = pubApiExtr.getPubApi("TestClass"); pubApiExtr.close(); // Validate result PubApi expectedApi = getExpectedPubApi(); if (!expectedApi.equals(actualApi)) { List diffs = expectedApi.diff(actualApi); System.out.println(diffs.size() + " differences found."); for (String diff : diffs) { System.out.println(diff); } throw new AssertionError("Actual API differs from expected API."); } } private static PubApi getExpectedPubApi() { ReferenceTypeDesc string = new ReferenceTypeDesc("java.lang.String"); // Fields // (s1 is private and therefore not included) PubVar s2 = new PubVar(setOf(PUBLIC), string, "s2", null); PubVar s4 = new PubVar(setOf(STATIC), string, "s4", null); PubVar s3 = new PubVar(setOf(PROTECTED, FINAL), string, "s3", "\"\\u0073\\u0074\\u0072\\u0020\\u0033\""); // Methods PubMethod init = new PubMethod(setOf(PUBLIC), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "", emptyList(), emptyList()); PubMethod clinit = new PubMethod(setOf(STATIC), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "", emptyList(), emptyList()); PubMethod m1 = new PubMethod(setOf(PROTECTED), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "m1", emptyList(), emptyList()); PubMethod m2 = new PubMethod(setOf(PUBLIC, STATIC), emptyList(), new ReferenceTypeDesc("java.util.Map"), "m2", emptyList(), emptyList()); PubMethod m3 = new PubMethod(setOf(FINAL), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "m3", asList(new ReferenceTypeDesc("java.util.Set")), emptyList()); // Complete class PubType testClass = new PubType(setOf(PUBLIC, FINAL), "TestClass", new PubApi(asList(getDummyInner1(), getDummyInner2()), asList(s2, s3, s4), asList(init, clinit, m1, m2, m3))); // Wrap in "package level" PubApi return new PubApi(asList(testClass), emptyList(), emptyList()); } private static PubType getDummyInner1() { PubMethod init = new PubMethod(setOf(), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "", emptyList(), emptyList()); PubMethod run = new PubMethod(setOf(PUBLIC), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "run", emptyList(), emptyList()); PubVar field = new PubVar(setOf(PROTECTED), new PrimitiveTypeDesc(TypeKind.INT), "field", null); return new PubType(setOf(STATIC), "TestClass$DummyInner1", new PubApi(emptyList(), asList(field), asList(init, run))); } private static PubType getDummyInner2() { PubMethod init = new PubMethod(setOf(), emptyList(), new PrimitiveTypeDesc(TypeKind.VOID), "", emptyList(), emptyList()); return new PubType(setOf(FINAL), "TestClass$DummyInner2", new PubApi(emptyList(), emptyList(), asList(init))); } @SafeVarargs private static Set setOf(T... elements) { return new HashSet<>(asList(elements)); } }