ApiExtraction.java revision 3034:c8206f440046
1/* 2 * Copyright (c) 2015, 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 8054717 27 * @summary Make sure extraction of non-private APIs work as expected. 28 * @library /tools/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.file 31 * jdk.compiler/com.sun.tools.javac.main 32 * jdk.compiler/com.sun.tools.sjavac 33 * @build Wrapper ToolBox 34 * @run main Wrapper ApiExtraction 35 */ 36import static java.util.Arrays.asList; 37import static java.util.Collections.emptyList; 38import static javax.lang.model.element.Modifier.FINAL; 39import static javax.lang.model.element.Modifier.PROTECTED; 40import static javax.lang.model.element.Modifier.PUBLIC; 41import static javax.lang.model.element.Modifier.STATIC; 42 43import java.io.IOException; 44import java.util.HashSet; 45import java.util.List; 46import java.util.Set; 47 48import javax.lang.model.type.TypeKind; 49 50import com.sun.tools.sjavac.PubApiExtractor; 51import com.sun.tools.sjavac.options.Options; 52import com.sun.tools.sjavac.pubapi.PrimitiveTypeDesc; 53import com.sun.tools.sjavac.pubapi.PubApi; 54import com.sun.tools.sjavac.pubapi.PubMethod; 55import com.sun.tools.sjavac.pubapi.PubType; 56import com.sun.tools.sjavac.pubapi.PubVar; 57import com.sun.tools.sjavac.pubapi.ReferenceTypeDesc; 58 59 60public class ApiExtraction { 61 public static void main(String[] args) throws IOException { 62 63 String testSrc = String.join("\n", 64 "import java.util.*;", 65 "public final class TestClass extends Thread {", 66 67 // Fields with various combination of modifiers 68 " private String s1 = \"str 1\";", 69 " public String s2 = \"str 2\";", 70 " protected final String s3 = \"str 3\";", 71 " static String s4 = \"str 4\";", 72 73 // Methods with various combinations of types and modifiers 74 " protected void m1() {}", 75 " public static Map<Integer, List<String>> m2() {", 76 " return null;", 77 " }", 78 " final void m3(Set<Map<Integer, Map<String, String>>> s) {}", 79 80 // Some inner classes 81 " static class DummyInner1 implements Runnable {", 82 " protected int field;", 83 " public void run() {}", 84 " }", 85 " final class DummyInner2 { }", 86 "}"); 87 88 // Create class file to extract API from 89 new ToolBox().new JavacTask().sources(testSrc).run(); 90 91 // Extract PubApi 92 Options options = Options.parseArgs("-d", "bin", "--state-dir=bin", "-cp", "."); 93 PubApiExtractor pubApiExtr = new PubApiExtractor(options); 94 PubApi actualApi = pubApiExtr.getPubApi("TestClass"); 95 96 // Validate result 97 PubApi expectedApi = getExpectedPubApi(); 98 if (!expectedApi.equals(actualApi)) { 99 List<String> diffs = expectedApi.diff(actualApi); 100 System.out.println(diffs.size() + " differences found."); 101 for (String diff : diffs) { 102 System.out.println(diff); 103 } 104 throw new AssertionError("Actual API differs from expected API."); 105 } 106 } 107 108 private static PubApi getExpectedPubApi() { 109 110 ReferenceTypeDesc string = new ReferenceTypeDesc("java.lang.String"); 111 112 // Fields 113 // (s1 is private and therefore not included) 114 PubVar s2 = new PubVar(setOf(PUBLIC), string, "s2", null); 115 PubVar s4 = new PubVar(setOf(STATIC), string, "s4", null); 116 PubVar s3 = new PubVar(setOf(PROTECTED, FINAL), string, "s3", 117 "\"\\u0073\\u0074\\u0072\\u0020\\u0033\""); 118 119 // Methods 120 PubMethod init = new PubMethod(setOf(PUBLIC), 121 emptyList(), 122 new PrimitiveTypeDesc(TypeKind.VOID), 123 "<init>", 124 emptyList(), 125 emptyList()); 126 127 PubMethod clinit = new PubMethod(setOf(STATIC), 128 emptyList(), 129 new PrimitiveTypeDesc(TypeKind.VOID), 130 "<clinit>", 131 emptyList(), 132 emptyList()); 133 134 PubMethod m1 = new PubMethod(setOf(PROTECTED), 135 emptyList(), 136 new PrimitiveTypeDesc(TypeKind.VOID), 137 "m1", 138 emptyList(), 139 emptyList()); 140 141 PubMethod m2 = new PubMethod(setOf(PUBLIC, STATIC), 142 emptyList(), 143 new ReferenceTypeDesc("java.util.Map"), 144 "m2", 145 emptyList(), 146 emptyList()); 147 148 PubMethod m3 = new PubMethod(setOf(FINAL), 149 emptyList(), 150 new PrimitiveTypeDesc(TypeKind.VOID), 151 "m3", 152 asList(new ReferenceTypeDesc("java.util.Set")), 153 emptyList()); 154 155 // Complete class 156 PubType testClass = new PubType(setOf(PUBLIC, FINAL), 157 "TestClass", 158 new PubApi(asList(getDummyInner1(), getDummyInner2()), 159 asList(s2, s3, s4), 160 asList(init, clinit, m1, m2, m3))); 161 162 // Wrap in "package level" PubApi 163 return new PubApi(asList(testClass), emptyList(), emptyList()); 164 } 165 166 private static PubType getDummyInner1() { 167 PubMethod init = new PubMethod(setOf(), 168 emptyList(), 169 new PrimitiveTypeDesc(TypeKind.VOID), 170 "<init>", 171 emptyList(), 172 emptyList()); 173 174 PubMethod run = new PubMethod(setOf(PUBLIC), 175 emptyList(), 176 new PrimitiveTypeDesc(TypeKind.VOID), 177 "run", 178 emptyList(), 179 emptyList()); 180 181 PubVar field = new PubVar(setOf(PROTECTED), 182 new PrimitiveTypeDesc(TypeKind.INT), 183 "field", 184 null); 185 186 return new PubType(setOf(STATIC), 187 "TestClass$DummyInner1", 188 new PubApi(emptyList(), 189 asList(field), 190 asList(init, run))); 191 } 192 193 private static PubType getDummyInner2() { 194 PubMethod init = new PubMethod(setOf(), 195 emptyList(), 196 new PrimitiveTypeDesc(TypeKind.VOID), 197 "<init>", 198 emptyList(), 199 emptyList()); 200 201 return new PubType(setOf(FINAL), 202 "TestClass$DummyInner2", 203 new PubApi(emptyList(), 204 emptyList(), 205 asList(init))); 206 } 207 208 @SafeVarargs 209 private static <T> Set<T> setOf(T... elements) { 210 return new HashSet<>(asList(elements)); 211 } 212} 213