ApiExtraction.java revision 3080:155f6671cab4
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        pubApiExtr.close();
96
97        // Validate result
98        PubApi expectedApi = getExpectedPubApi();
99        if (!expectedApi.equals(actualApi)) {
100            List<String> diffs = expectedApi.diff(actualApi);
101            System.out.println(diffs.size() + " differences found.");
102            for (String diff : diffs) {
103                System.out.println(diff);
104            }
105            throw new AssertionError("Actual API differs from expected API.");
106        }
107    }
108
109    private static PubApi getExpectedPubApi() {
110
111        ReferenceTypeDesc string = new ReferenceTypeDesc("java.lang.String");
112
113        // Fields
114        // (s1 is private and therefore not included)
115        PubVar s2 = new PubVar(setOf(PUBLIC), string, "s2", null);
116        PubVar s4 = new PubVar(setOf(STATIC), string, "s4", null);
117        PubVar s3 = new PubVar(setOf(PROTECTED, FINAL), string, "s3",
118                                   "\"\\u0073\\u0074\\u0072\\u0020\\u0033\"");
119
120        // Methods
121        PubMethod init = new PubMethod(setOf(PUBLIC),
122                                       emptyList(),
123                                       new PrimitiveTypeDesc(TypeKind.VOID),
124                                       "<init>",
125                                       emptyList(),
126                                       emptyList());
127
128        PubMethod clinit = new PubMethod(setOf(STATIC),
129                                         emptyList(),
130                                         new PrimitiveTypeDesc(TypeKind.VOID),
131                                         "<clinit>",
132                                         emptyList(),
133                                         emptyList());
134
135        PubMethod m1 = new PubMethod(setOf(PROTECTED),
136                                     emptyList(),
137                                     new PrimitiveTypeDesc(TypeKind.VOID),
138                                     "m1",
139                                     emptyList(),
140                                     emptyList());
141
142        PubMethod m2 = new PubMethod(setOf(PUBLIC, STATIC),
143                                     emptyList(),
144                                     new ReferenceTypeDesc("java.util.Map"),
145                                     "m2",
146                                     emptyList(),
147                                     emptyList());
148
149        PubMethod m3 = new PubMethod(setOf(FINAL),
150                                     emptyList(),
151                                     new PrimitiveTypeDesc(TypeKind.VOID),
152                                     "m3",
153                                     asList(new ReferenceTypeDesc("java.util.Set")),
154                                     emptyList());
155
156        // Complete class
157        PubType testClass = new PubType(setOf(PUBLIC, FINAL),
158                                        "TestClass",
159                                        new PubApi(asList(getDummyInner1(), getDummyInner2()),
160                                                   asList(s2, s3, s4),
161                                                   asList(init, clinit, m1, m2, m3)));
162
163        // Wrap in "package level" PubApi
164        return new PubApi(asList(testClass), emptyList(), emptyList());
165    }
166
167    private static PubType getDummyInner1() {
168        PubMethod init = new PubMethod(setOf(),
169                                       emptyList(),
170                                       new PrimitiveTypeDesc(TypeKind.VOID),
171                                       "<init>",
172                                       emptyList(),
173                                       emptyList());
174
175        PubMethod run = new PubMethod(setOf(PUBLIC),
176                                      emptyList(),
177                                      new PrimitiveTypeDesc(TypeKind.VOID),
178                                      "run",
179                                      emptyList(),
180                                      emptyList());
181
182        PubVar field = new PubVar(setOf(PROTECTED),
183                                  new PrimitiveTypeDesc(TypeKind.INT),
184                                  "field",
185                                  null);
186
187        return new PubType(setOf(STATIC),
188                           "TestClass$DummyInner1",
189                           new PubApi(emptyList(),
190                                      asList(field),
191                                      asList(init, run)));
192    }
193
194    private static PubType getDummyInner2() {
195        PubMethod init = new PubMethod(setOf(),
196                                       emptyList(),
197                                       new PrimitiveTypeDesc(TypeKind.VOID),
198                                       "<init>",
199                                       emptyList(),
200                                       emptyList());
201
202        return new PubType(setOf(FINAL),
203                           "TestClass$DummyInner2",
204                           new PubApi(emptyList(),
205                                      emptyList(),
206                                      asList(init)));
207    }
208
209    @SafeVarargs
210    private static <T> Set<T> setOf(T... elements) {
211        return new HashSet<>(asList(elements));
212    }
213}
214