BasicJavacTask.java revision 2973:0e8fa3249327
1/*
2 * Copyright (c) 2005, 2014, 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.javac.api;
27
28import java.util.Collection;
29import java.util.LinkedHashSet;
30import java.util.Locale;
31import java.util.Set;
32import java.util.stream.Collectors;
33
34import javax.annotation.processing.Processor;
35import javax.lang.model.element.Element;
36import javax.lang.model.type.TypeMirror;
37import javax.lang.model.util.Elements;
38import javax.lang.model.util.Types;
39import javax.tools.JavaFileObject;
40
41import com.sun.source.tree.CompilationUnitTree;
42import com.sun.source.tree.Tree;
43import com.sun.source.util.JavacTask;
44import com.sun.source.util.Plugin;
45import com.sun.source.util.TaskListener;
46import com.sun.tools.doclint.DocLint;
47import com.sun.tools.javac.main.JavaCompiler;
48import com.sun.tools.javac.model.JavacElements;
49import com.sun.tools.javac.model.JavacTypes;
50import com.sun.tools.javac.platform.PlatformDescription;
51import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
52import com.sun.tools.javac.processing.JavacProcessingEnvironment;
53import com.sun.tools.javac.tree.JCTree;
54import com.sun.tools.javac.util.Context;
55import com.sun.tools.javac.util.DefinedBy;
56import com.sun.tools.javac.util.DefinedBy.Api;
57import com.sun.tools.javac.util.List;
58import com.sun.tools.javac.util.Log;
59import com.sun.tools.javac.util.PropagatedException;
60import com.sun.tools.javac.util.ServiceLoader;
61
62/**
63 * Provides basic functionality for implementations of JavacTask.
64 *
65 * <p><b>This is NOT part of any supported API.
66 * If you write code that depends on this, you do so at your own
67 * risk.  This code and its internal interfaces are subject to change
68 * or deletion without notice.</b></p>
69 */
70public class BasicJavacTask extends JavacTask {
71    protected Context context;
72    private TaskListener taskListener;
73
74    public static JavacTask instance(Context context) {
75        JavacTask instance = context.get(JavacTask.class);
76        if (instance == null)
77            instance = new BasicJavacTask(context, true);
78        return instance;
79    }
80
81    public BasicJavacTask(Context c, boolean register) {
82        context = c;
83        if (register)
84            context.put(JavacTask.class, this);
85    }
86
87    @Override @DefinedBy(Api.COMPILER_TREE)
88    public Iterable<? extends CompilationUnitTree> parse() {
89        throw new IllegalStateException();
90    }
91
92    @Override @DefinedBy(Api.COMPILER_TREE)
93    public Iterable<? extends Element> analyze() {
94        throw new IllegalStateException();
95    }
96
97    @Override @DefinedBy(Api.COMPILER_TREE)
98    public Iterable<? extends JavaFileObject> generate() {
99        throw new IllegalStateException();
100    }
101
102    @Override @DefinedBy(Api.COMPILER_TREE)
103    public void setTaskListener(TaskListener tl) {
104        MultiTaskListener mtl = MultiTaskListener.instance(context);
105        if (taskListener != null)
106            mtl.remove(taskListener);
107        if (tl != null)
108            mtl.add(tl);
109        taskListener = tl;
110    }
111
112    @Override @DefinedBy(Api.COMPILER_TREE)
113    public void addTaskListener(TaskListener taskListener) {
114        MultiTaskListener mtl = MultiTaskListener.instance(context);
115        mtl.add(taskListener);
116    }
117
118    @Override @DefinedBy(Api.COMPILER_TREE)
119    public void removeTaskListener(TaskListener taskListener) {
120        MultiTaskListener mtl = MultiTaskListener.instance(context);
121        mtl.remove(taskListener);
122    }
123
124    public Collection<TaskListener> getTaskListeners() {
125        MultiTaskListener mtl = MultiTaskListener.instance(context);
126        return mtl.getTaskListeners();
127    }
128
129    @Override @DefinedBy(Api.COMPILER_TREE)
130    public TypeMirror getTypeMirror(Iterable<? extends Tree> path) {
131        // TODO: Should complete attribution if necessary
132        Tree last = null;
133        for (Tree node : path)
134            last = node;
135        return ((JCTree)last).type;
136    }
137
138    @Override @DefinedBy(Api.COMPILER_TREE)
139    public Elements getElements() {
140        if (context == null)
141            throw new IllegalStateException();
142        return JavacElements.instance(context);
143    }
144
145    @Override @DefinedBy(Api.COMPILER_TREE)
146    public Types getTypes() {
147        if (context == null)
148            throw new IllegalStateException();
149        return JavacTypes.instance(context);
150    }
151
152    @Override @DefinedBy(Api.COMPILER)
153    public void setProcessors(Iterable<? extends Processor> processors) {
154        throw new IllegalStateException();
155    }
156
157    @Override @DefinedBy(Api.COMPILER)
158    public void setLocale(Locale locale) {
159        throw new IllegalStateException();
160    }
161
162    @Override @DefinedBy(Api.COMPILER)
163    public Boolean call() {
164        throw new IllegalStateException();
165    }
166
167    /**
168     * For internal use only.
169     * This method will be removed without warning.
170     * @return the context
171     */
172    public Context getContext() {
173        return context;
174    }
175
176    public void initPlugins(Set<List<String>> pluginOpts) {
177        PlatformDescription platformProvider = context.get(PlatformDescription.class);
178
179        if (platformProvider != null) {
180            for (PluginInfo<Plugin> pluginDesc : platformProvider.getPlugins()) {
181                java.util.List<String> options =
182                        pluginDesc.getOptions().entrySet().stream()
183                                                          .map(e -> e.getKey() + "=" + e.getValue())
184                                                          .collect(Collectors.toList());
185                try {
186                    pluginDesc.getPlugin().init(this, options.toArray(new String[options.size()]));
187                } catch (RuntimeException ex) {
188                    throw new PropagatedException(ex);
189                }
190            }
191        }
192
193        if (pluginOpts.isEmpty())
194            return;
195
196        Set<List<String>> pluginsToCall = new LinkedHashSet<>(pluginOpts);
197        JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context);
198        ClassLoader cl = pEnv.getProcessorClassLoader();
199        ServiceLoader<Plugin> sl = ServiceLoader.load(Plugin.class, cl);
200        for (Plugin plugin : sl) {
201            for (List<String> p : pluginsToCall) {
202                if (plugin.getName().equals(p.head)) {
203                    pluginsToCall.remove(p);
204                    try {
205                        plugin.init(this, p.tail.toArray(new String[p.tail.size()]));
206                    } catch (RuntimeException ex) {
207                        throw new PropagatedException(ex);
208                    }
209                }
210            }
211        }
212        for (List<String> p: pluginsToCall) {
213            Log.instance(context).error("plugin.not.found", p.head);
214        }
215    }
216
217    public void initDocLint(List<String> docLintOpts) {
218        if (docLintOpts.isEmpty())
219            return;
220
221        new DocLint().init(this, docLintOpts.toArray(new String[docLintOpts.size()]));
222        JavaCompiler.instance(context).keepComments = true;
223    }
224}
225