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