ToolProvider.java revision 2774:70d213c84585
1227825Stheraven/* 2227825Stheraven * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3227825Stheraven * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4353358Sdim * 5353358Sdim * This code is free software; you can redistribute it and/or modify it 6353358Sdim * under the terms of the GNU General Public License version 2 only, as 7227825Stheraven * published by the Free Software Foundation. Oracle designates this 8227825Stheraven * particular file as subject to the "Classpath" exception as provided 9227825Stheraven * by Oracle in the LICENSE file that accompanied this code. 10227825Stheraven * 11227825Stheraven * This code is distributed in the hope that it will be useful, but WITHOUT 12227825Stheraven * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13227825Stheraven * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14227825Stheraven * version 2 for more details (a copy is included in the LICENSE file that 15227825Stheraven * accompanied this code). 16261272Sdim * 17261272Sdim * You should have received a copy of the GNU General Public License version 18227825Stheraven * 2 along with this work; if not, write to the Free Software Foundation, 19227825Stheraven * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20227825Stheraven * 21227825Stheraven * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22227825Stheraven * or visit www.oracle.com if you need additional information or have any 23227825Stheraven * questions. 24227825Stheraven */ 25227825Stheraven 26227825Stheravenpackage javax.tools; 27227825Stheraven 28227825Stheravenimport java.lang.ref.Reference; 29227825Stheravenimport java.lang.ref.WeakReference; 30261272Sdimimport java.util.HashMap; 31261272Sdimimport java.util.Locale; 32261272Sdimimport java.util.Map; 33261272Sdimimport java.util.logging.Logger; 34261272Sdimimport java.util.logging.Level; 35261272Sdim 36261272Sdimimport static java.util.logging.Level.*; 37261272Sdim 38261272Sdim/** 39261272Sdim * Provides methods for locating tool providers, for example, 40261272Sdim * providers of compilers. This class complements the 41227825Stheraven * functionality of {@link java.util.ServiceLoader}. 42227825Stheraven * 43227825Stheraven * @author Peter von der Ahé 44227825Stheraven * @since 1.6 45227825Stheraven */ 46314564Sdimpublic class ToolProvider { 47227825Stheraven 48344779Sdim private static final String propertyName = "sun.tools.ToolProvider"; 49227825Stheraven private static final String loggerName = "javax.tools"; 50227825Stheraven 51227825Stheraven /* 52227825Stheraven * Define the system property "sun.tools.ToolProvider" to enable 53227825Stheraven * debugging: 54227825Stheraven * 55227825Stheraven * java ... -Dsun.tools.ToolProvider ... 56227825Stheraven */ 57227825Stheraven static <T> T trace(Level level, Object reason) { 58227825Stheraven // NOTE: do not make this method private as it affects stack traces 59227825Stheraven try { 60227825Stheraven if (System.getProperty(propertyName) != null) { 61227825Stheraven StackTraceElement[] st = Thread.currentThread().getStackTrace(); 62227825Stheraven String method = "???"; 63227825Stheraven String cls = ToolProvider.class.getName(); 64227825Stheraven if (st.length > 2) { 65227825Stheraven StackTraceElement frame = st[2]; 66227825Stheraven method = String.format((Locale)null, "%s(%s:%s)", 67227825Stheraven frame.getMethodName(), 68227825Stheraven frame.getFileName(), 69227825Stheraven frame.getLineNumber()); 70227825Stheraven cls = frame.getClassName(); 71227825Stheraven } 72227825Stheraven Logger logger = Logger.getLogger(loggerName); 73227825Stheraven if (reason instanceof Throwable) { 74227825Stheraven logger.logp(level, cls, method, 75227825Stheraven reason.getClass().getName(), (Throwable)reason); 76227825Stheraven } else { 77227825Stheraven logger.logp(level, cls, method, String.valueOf(reason)); 78227825Stheraven } 79227825Stheraven } 80227825Stheraven } catch (SecurityException ex) { 81227825Stheraven System.err.format((Locale)null, "%s: %s; %s%n", 82227825Stheraven ToolProvider.class.getName(), 83227825Stheraven reason, 84227825Stheraven ex.getLocalizedMessage()); 85227825Stheraven } 86227825Stheraven return null; 87227825Stheraven } 88227825Stheraven 89227825Stheraven private static final String systemJavaCompilerName 90227825Stheraven = "com.sun.tools.javac.api.JavacTool"; 91227825Stheraven 92227825Stheraven /** 93227825Stheraven * Returns the Java™ programming language compiler provided 94227825Stheraven * with this platform. 95227825Stheraven * <p>The file manager returned by calling 96227825Stheraven * {@link JavaCompiler#getStandardFileManager getStandardFileManager} 97227825Stheraven * on this compiler supports paths provided by any 98227825Stheraven * {@linkplain java.nio.file.FileSystem filesystem}.</p> 99227825Stheraven * @return the compiler provided with this platform or 100227825Stheraven * {@code null} if no compiler is provided 101227825Stheraven */ 102227825Stheraven public static JavaCompiler getSystemJavaCompiler() { 103227825Stheraven return instance().getSystemTool(JavaCompiler.class, systemJavaCompilerName); 104227825Stheraven } 105227825Stheraven 106227825Stheraven private static final String systemDocumentationToolName 107227825Stheraven = "com.sun.tools.javadoc.api.JavadocTool"; 108227825Stheraven 109227825Stheraven /** 110227825Stheraven * Returns the Java™ programming language documentation tool provided 111227825Stheraven * with this platform. 112227825Stheraven * <p>The file manager returned by calling 113227825Stheraven * {@link DocumentationTool#getStandardFileManager getStandardFileManager} 114227825Stheraven * on this tool supports paths provided by any 115227825Stheraven * {@linkplain java.nio.file.FileSystem filesystem}.</p> 116227825Stheraven * @return the documentation tool provided with this platform or 117227825Stheraven * {@code null} if no documentation tool is provided 118227825Stheraven */ 119227825Stheraven public static DocumentationTool getSystemDocumentationTool() { 120227825Stheraven return instance().getSystemTool(DocumentationTool.class, systemDocumentationToolName); 121227825Stheraven } 122227825Stheraven 123227825Stheraven /** 124227825Stheraven * Returns the class loader for tools provided with this platform. 125227825Stheraven * This does not include user-installed tools. Use the 126227825Stheraven * {@linkplain java.util.ServiceLoader service provider mechanism} 127227825Stheraven * for locating user installed tools. 128227825Stheraven * 129227825Stheraven * @return the class loader for tools provided with this platform 130227825Stheraven * or {@code null} if no tools are provided 131227825Stheraven */ 132227825Stheraven public static ClassLoader getSystemToolClassLoader() { 133227825Stheraven return ClassLoader.getSystemClassLoader(); 134227825Stheraven } 135227825Stheraven 136227825Stheraven 137227825Stheraven private static ToolProvider instance; 138227825Stheraven 139227825Stheraven private static synchronized ToolProvider instance() { 140227825Stheraven if (instance == null) 141227825Stheraven instance = new ToolProvider(); 142227825Stheraven return instance; 143227825Stheraven } 144227825Stheraven 145227825Stheraven // Cache for tool classes. 146227825Stheraven // Use weak references to avoid keeping classes around unnecessarily 147227825Stheraven private final Map<String, Reference<Class<?>>> toolClasses = new HashMap<>(); 148227825Stheraven 149227825Stheraven private ToolProvider() { } 150227825Stheraven 151227825Stheraven private <T> T getSystemTool(Class<T> clazz, String name) { 152227825Stheraven Class<? extends T> c = getSystemToolClass(clazz, name); 153227825Stheraven try { 154227825Stheraven return c.asSubclass(clazz).newInstance(); 155227825Stheraven } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) { 156227825Stheraven return trace(WARNING, e); 157227825Stheraven } 158227825Stheraven } 159227825Stheraven 160227825Stheraven private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) { 161227825Stheraven Reference<Class<?>> refClass = toolClasses.get(name); 162227825Stheraven Class<?> c = (refClass == null ? null : refClass.get()); 163227825Stheraven if (c == null) { 164227825Stheraven try { 165227825Stheraven c = Class.forName(name, false, ClassLoader.getSystemClassLoader()); 166227825Stheraven } catch (ClassNotFoundException | RuntimeException | Error e) { 167227825Stheraven return trace(WARNING, e); 168227825Stheraven } 169227825Stheraven toolClasses.put(name, new WeakReference<>(c)); 170227825Stheraven } 171227825Stheraven return c.asSubclass(clazz); 172227825Stheraven } 173227825Stheraven} 174227825Stheraven