ToolProvider.java revision 3260:f04e97a97930
1/*
2 * Copyright (c) 2005, 2016, 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 javax.tools;
27
28import java.lang.ref.Reference;
29import java.lang.ref.WeakReference;
30import java.util.HashMap;
31import java.util.Map;
32
33/**
34 * Provides methods for locating tool providers, for example,
35 * providers of compilers.  This class complements the
36 * functionality of {@link java.util.ServiceLoader}.
37 *
38 * @author Peter von der Ahé
39 * @since 1.6
40 */
41public class ToolProvider {
42
43    private static final String systemJavaCompilerName
44        = "com.sun.tools.javac.api.JavacTool";
45
46    /**
47     * Returns the Java™ programming language compiler provided
48     * with this platform.
49     * <p>The file manager returned by calling
50     * {@link JavaCompiler#getStandardFileManager getStandardFileManager}
51     * on this compiler supports paths provided by any
52     * {@linkplain java.nio.file.FileSystem filesystem}.</p>
53     * @return the compiler provided with this platform or
54     * {@code null} if no compiler is provided
55     */
56    public static JavaCompiler getSystemJavaCompiler() {
57        return instance().getSystemTool(JavaCompiler.class, systemJavaCompilerName);
58    }
59
60    private static final String systemDocumentationToolName
61        = "jdk.javadoc.internal.api.JavadocTool";
62
63    /**
64     * Returns the Java&trade; programming language documentation tool provided
65     * with this platform.
66     * <p>The file manager returned by calling
67     * {@link DocumentationTool#getStandardFileManager getStandardFileManager}
68     * on this tool supports paths provided by any
69     * {@linkplain java.nio.file.FileSystem filesystem}.</p>
70     * @return the documentation tool provided with this platform or
71     * {@code null} if no documentation tool is provided
72     */
73    public static DocumentationTool getSystemDocumentationTool() {
74        return instance().getSystemTool(DocumentationTool.class, systemDocumentationToolName);
75    }
76
77    /**
78     * Returns the class loader for tools provided with this platform.
79     * This does not include user-installed tools.  Use the
80     * {@linkplain java.util.ServiceLoader service provider mechanism}
81     * for locating user installed tools.
82     *
83     * @return the class loader for tools provided with this platform
84     * or {@code null} if no tools are provided
85     */
86    public static ClassLoader getSystemToolClassLoader() {
87        return ClassLoader.getSystemClassLoader();
88    }
89
90
91    private static ToolProvider instance;
92
93    private static synchronized ToolProvider instance() {
94        if (instance == null)
95            instance = new ToolProvider();
96        return instance;
97    }
98
99    // Cache for tool classes.
100    // Use weak references to avoid keeping classes around unnecessarily
101    private final Map<String, Reference<Class<?>>> toolClasses = new HashMap<>();
102
103    private ToolProvider() { }
104
105    private <T> T getSystemTool(Class<T> clazz, String name) {
106        Class<? extends T> c = getSystemToolClass(clazz, name);
107        try {
108            return c.asSubclass(clazz).newInstance();
109        } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) {
110            throw new Error(e);
111        }
112    }
113
114    private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) {
115        Reference<Class<?>> refClass = toolClasses.get(name);
116        Class<?> c = (refClass == null ? null : refClass.get());
117        if (c == null) {
118            try {
119                c = Class.forName(name, false, ClassLoader.getSystemClassLoader());
120            } catch (ClassNotFoundException | RuntimeException | Error e) {
121                throw new Error(e);
122            }
123            toolClasses.put(name, new WeakReference<>(c));
124        }
125        return c.asSubclass(clazz);
126    }
127}
128