ApiExtraction.java revision 2958:27da0c3ac83a
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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26/* 27 * @test 28 * @bug 8054717 29 * @summary Make sure extraction of non-private APIs work as expected. 30 * @library /tools/lib 31 * @modules jdk.compiler/com.sun.tools.javac.api 32 * jdk.compiler/com.sun.tools.javac.file 33 * jdk.compiler/com.sun.tools.javac.main 34 * jdk.compiler/com.sun.tools.sjavac 35 * @build Wrapper ToolBox 36 * @run main Wrapper ApiExtraction 37 */ 38import static java.util.Arrays.asList; 39import static java.util.Collections.emptyList; 40import static javax.lang.model.element.Modifier.FINAL; 41import static javax.lang.model.element.Modifier.PROTECTED; 42import static javax.lang.model.element.Modifier.PUBLIC; 43import static javax.lang.model.element.Modifier.STATIC; 44 45import java.io.IOException; 46import java.util.HashSet; 47import java.util.List; 48import java.util.Set; 49 50import javax.lang.model.type.TypeKind; 51 52import com.sun.tools.sjavac.PubApiExtractor; 53import com.sun.tools.sjavac.options.Options; 54import com.sun.tools.sjavac.pubapi.PrimitiveTypeDesc; 55import com.sun.tools.sjavac.pubapi.PubApi; 56import com.sun.tools.sjavac.pubapi.PubMethod; 57import com.sun.tools.sjavac.pubapi.PubType; 58import com.sun.tools.sjavac.pubapi.PubVar; 59import com.sun.tools.sjavac.pubapi.ReferenceTypeDesc; 60 61 62public class ApiExtraction { 63 public static void main(String[] args) throws IOException { 64 65 String testSrc = String.join("\n", 66 "import java.util.*;", 67 "public final class TestClass extends Thread {", 68 69 // Fields with various combination of modifiers 70 " private String s1 = \"str 1\";", 71 " public String s2 = \"str 2\";", 72 " protected final String s3 = \"str 3\";", 73 " static String s4 = \"str 4\";", 74 75 // Methods with various combinations of types and modifiers 76 " protected void m1() {}", 77 " public static Map<Integer, List<String>> m2() {", 78 " return null;", 79 " }", 80 " final void m3(Set<Map<Integer, Map<String, String>>> s) {}", 81 82 // Some inner classes 83 " static class DummyInner1 implements Runnable {", 84 " protected int field;", 85 " public void run() {}", 86 " }", 87 " final class DummyInner2 { }", 88 "}"); 89 90 // Create class file to extract API from 91 new ToolBox().new JavacTask().sources(testSrc).run(); 92 93 // Extract PubApi 94 Options options = Options.parseArgs("-d", "bin", "-cp", "."); 95 PubApiExtractor pubApiExtr = new PubApiExtractor(options); 96 PubApi actualApi = pubApiExtr.getPubApi("TestClass"); 97 98 // Validate result 99 PubApi expectedApi = getExpectedPubApi(); 100 if (!expectedApi.equals(actualApi)) { 101 List<String> diffs = expectedApi.diff(actualApi); 102 System.out.println(diffs.size() + " differences found."); 103 for (String diff : diffs) { 104 System.out.println(diff); 105 } 106 throw new AssertionError("Actual API differs from expected API."); 107 } 108 } 109 110 private static PubApi getExpectedPubApi() { 111 112 ReferenceTypeDesc string = new ReferenceTypeDesc("java.lang.String"); 113 114 // Fields 115 // (s1 is private and therefore not included) 116 PubVar s2 = new PubVar(setOf(PUBLIC), string, "s2", null); 117 PubVar s4 = new PubVar(setOf(STATIC), string, "s4", null); 118 PubVar s3 = new PubVar(setOf(PROTECTED, FINAL), string, "s3", 119 "\"\\u0073\\u0074\\u0072\\u0020\\u0033\""); 120 121 // Methods 122 PubMethod init = new PubMethod(setOf(PUBLIC), 123 emptyList(), 124 new PrimitiveTypeDesc(TypeKind.VOID), 125 "<init>", 126 emptyList(), 127 emptyList()); 128 129 PubMethod clinit = new PubMethod(setOf(STATIC), 130 emptyList(), 131 new PrimitiveTypeDesc(TypeKind.VOID), 132 "<clinit>", 133 emptyList(), 134 emptyList()); 135 136 PubMethod m1 = new PubMethod(setOf(PROTECTED), 137 emptyList(), 138 new PrimitiveTypeDesc(TypeKind.VOID), 139 "m1", 140 emptyList(), 141 emptyList()); 142 143 PubMethod m2 = new PubMethod(setOf(PUBLIC, STATIC), 144 emptyList(), 145 new ReferenceTypeDesc("java.util.Map"), 146 "m2", 147 emptyList(), 148 emptyList()); 149 150 PubMethod m3 = new PubMethod(setOf(FINAL), 151 emptyList(), 152 new PrimitiveTypeDesc(TypeKind.VOID), 153 "m3", 154 asList(new ReferenceTypeDesc("java.util.Set")), 155 emptyList()); 156 157 // Complete class 158 PubType testClass = new PubType(setOf(PUBLIC, FINAL), 159 "TestClass", 160 new PubApi(asList(getDummyInner1(), getDummyInner2()), 161 asList(s2, s3, s4), 162 asList(init, clinit, m1, m2, m3))); 163 164 // Wrap in "package level" PubApi 165 return new PubApi(asList(testClass), emptyList(), emptyList()); 166 } 167 168 private static PubType getDummyInner1() { 169 PubMethod init = new PubMethod(setOf(), 170 emptyList(), 171 new PrimitiveTypeDesc(TypeKind.VOID), 172 "<init>", 173 emptyList(), 174 emptyList()); 175 176 PubMethod run = new PubMethod(setOf(PUBLIC), 177 emptyList(), 178 new PrimitiveTypeDesc(TypeKind.VOID), 179 "run", 180 emptyList(), 181 emptyList()); 182 183 PubVar field = new PubVar(setOf(PROTECTED), 184 new PrimitiveTypeDesc(TypeKind.INT), 185 "field", 186 null); 187 188 return new PubType(setOf(STATIC), 189 "TestClass$DummyInner1", 190 new PubApi(emptyList(), 191 asList(field), 192 asList(init, run))); 193 } 194 195 private static PubType getDummyInner2() { 196 PubMethod init = new PubMethod(setOf(), 197 emptyList(), 198 new PrimitiveTypeDesc(TypeKind.VOID), 199 "<init>", 200 emptyList(), 201 emptyList()); 202 203 return new PubType(setOf(FINAL), 204 "TestClass$DummyInner2", 205 new PubApi(emptyList(), 206 emptyList(), 207 asList(init))); 208 } 209 210 @SafeVarargs 211 private static <T> Set<T> setOf(T... elements) { 212 return new HashSet<>(asList(elements)); 213 } 214} 215