PublicApiCollector.java revision 2958:27da0c3ac83a
1/*
2 * Copyright (c) 2014, 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
26package com.sun.tools.sjavac.comp.dependencies;
27
28import java.util.Collection;
29import java.util.HashSet;
30import java.util.Map;
31import java.util.Set;
32
33import javax.tools.JavaFileObject;
34
35import com.sun.source.tree.Tree;
36import com.sun.source.util.TaskEvent;
37import com.sun.source.util.TaskListener;
38import com.sun.tools.javac.code.Symbol.ClassSymbol;
39import com.sun.tools.javac.tree.JCTree.JCClassDecl;
40import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
41import com.sun.tools.javac.util.Context;
42import com.sun.tools.javac.util.DefinedBy;
43import com.sun.tools.javac.util.DefinedBy.Api;
44import com.sun.tools.sjavac.Log;
45import com.sun.tools.sjavac.comp.PubAPIs;
46import com.sun.tools.sjavac.pubapi.PubApi;
47
48
49public class PublicApiCollector implements TaskListener {
50
51    private Context context;
52    private final Set<ClassSymbol> classSymbols = new HashSet<>();
53    private final Collection<JavaFileObject> explicitJFOs;
54
55    // Result collected upon compilation task finished
56    private Map<String, PubApi> explicitPubApis;
57    private Map<String, PubApi> nonExplicitPubApis;
58
59    public PublicApiCollector(Context context,
60                              Collection<JavaFileObject> explicitJFOs) {
61        this.context = context;
62        this.explicitJFOs = explicitJFOs;
63    }
64
65    @Override
66    @DefinedBy(Api.COMPILER_TREE)
67    public void finished(TaskEvent e) {
68        switch (e.getKind()) {
69        case ANALYZE:
70            collectClassSymbols((JCCompilationUnit) e.getCompilationUnit());
71            break;
72        case COMPILATION:
73            Log.debug("Compilation finished");
74            Log.debug("Extracting pub APIs for the following symbols:");
75            for (ClassSymbol cs : classSymbols)
76                Log.debug("    " + cs.fullname);
77            extractPubApis();
78
79            // Save result for later retrieval. (Important that we do this
80            // before we return from this method, because we may not access
81            // symbols after compilation is finished.)
82            PubAPIs pa = PubAPIs.instance(context);
83            explicitPubApis = pa.getPubapis(explicitJFOs, true);
84            nonExplicitPubApis = pa.getPubapis(explicitJFOs, false);
85
86            Log.debug("done");
87            break;
88        }
89    }
90
91    private void collectClassSymbols(JCCompilationUnit cu) {
92        for (Tree t : cu.getTypeDecls()) {
93            if (t instanceof JCClassDecl)  // Can also be a JCSkip
94                classSymbols.add(((JCClassDecl) t).sym);
95        }
96    }
97
98    private void extractPubApis() {
99        // To handle incremental builds (subsequent sjavac invocations) we need
100        // to keep track of the public API of what we depend upon.
101        //
102        // During the recompilation loop (within a single sjavac invocation) we
103        // need to keep track of public API of what we're compiling to decide if
104        // any dependants needs to be tainted.
105        PubAPIs pubApis = PubAPIs.instance(context);
106        classSymbols.forEach(pubApis::visitPubapi);
107    }
108
109    public Map<String, PubApi> getPubApis(boolean explicit) {
110        return explicit ? explicitPubApis : nonExplicitPubApis;
111    }
112}
113