ToolProvider.java revision 2721:f7ce2cfa4cdb
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 javax.tools; 27 28import java.lang.ref.Reference; 29import java.lang.ref.WeakReference; 30import java.util.HashMap; 31import java.util.Locale; 32import java.util.Map; 33import java.util.logging.Logger; 34import java.util.logging.Level; 35 36import static java.util.logging.Level.*; 37 38/** 39 * Provides methods for locating tool providers, for example, 40 * providers of compilers. This class complements the 41 * functionality of {@link java.util.ServiceLoader}. 42 * 43 * @author Peter von der Ahé 44 * @since 1.6 45 */ 46public class ToolProvider { 47 48 private static final String propertyName = "sun.tools.ToolProvider"; 49 private static final String loggerName = "javax.tools"; 50 51 /* 52 * Define the system property "sun.tools.ToolProvider" to enable 53 * debugging: 54 * 55 * java ... -Dsun.tools.ToolProvider ... 56 */ 57 static <T> T trace(Level level, Object reason) { 58 // NOTE: do not make this method private as it affects stack traces 59 try { 60 if (System.getProperty(propertyName) != null) { 61 StackTraceElement[] st = Thread.currentThread().getStackTrace(); 62 String method = "???"; 63 String cls = ToolProvider.class.getName(); 64 if (st.length > 2) { 65 StackTraceElement frame = st[2]; 66 method = String.format((Locale)null, "%s(%s:%s)", 67 frame.getMethodName(), 68 frame.getFileName(), 69 frame.getLineNumber()); 70 cls = frame.getClassName(); 71 } 72 Logger logger = Logger.getLogger(loggerName); 73 if (reason instanceof Throwable) { 74 logger.logp(level, cls, method, 75 reason.getClass().getName(), (Throwable)reason); 76 } else { 77 logger.logp(level, cls, method, String.valueOf(reason)); 78 } 79 } 80 } catch (SecurityException ex) { 81 System.err.format((Locale)null, "%s: %s; %s%n", 82 ToolProvider.class.getName(), 83 reason, 84 ex.getLocalizedMessage()); 85 } 86 return null; 87 } 88 89 private static final String systemJavaCompilerName 90 = "com.sun.tools.javac.api.JavacTool"; 91 92 /** 93 * Returns the Java™ programming language compiler provided 94 * with this platform. 95 * @return the compiler provided with this platform or 96 * {@code null} if no compiler is provided 97 */ 98 public static JavaCompiler getSystemJavaCompiler() { 99 return instance().getSystemTool(JavaCompiler.class, systemJavaCompilerName); 100 } 101 102 private static final String systemDocumentationToolName 103 = "com.sun.tools.javadoc.api.JavadocTool"; 104 105 /** 106 * Returns the Java™ programming language documentation tool provided 107 * with this platform. 108 * @return the documentation tool provided with this platform or 109 * {@code null} if no documentation tool is provided 110 */ 111 public static DocumentationTool getSystemDocumentationTool() { 112 return instance().getSystemTool(DocumentationTool.class, systemDocumentationToolName); 113 } 114 115 /** 116 * Returns the class loader for tools provided with this platform. 117 * This does not include user-installed tools. Use the 118 * {@linkplain java.util.ServiceLoader service provider mechanism} 119 * for locating user installed tools. 120 * 121 * @return the class loader for tools provided with this platform 122 * or {@code null} if no tools are provided 123 */ 124 public static ClassLoader getSystemToolClassLoader() { 125 return ClassLoader.getSystemClassLoader(); 126 } 127 128 129 private static ToolProvider instance; 130 131 private static synchronized ToolProvider instance() { 132 if (instance == null) 133 instance = new ToolProvider(); 134 return instance; 135 } 136 137 // Cache for tool classes. 138 // Use weak references to avoid keeping classes around unnecessarily 139 private final Map<String, Reference<Class<?>>> toolClasses = new HashMap<>(); 140 141 private ToolProvider() { } 142 143 private <T> T getSystemTool(Class<T> clazz, String name) { 144 Class<? extends T> c = getSystemToolClass(clazz, name); 145 try { 146 return c.asSubclass(clazz).newInstance(); 147 } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) { 148 return trace(WARNING, e); 149 } 150 } 151 152 private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) { 153 Reference<Class<?>> refClass = toolClasses.get(name); 154 Class<?> c = (refClass == null ? null : refClass.get()); 155 if (c == null) { 156 try { 157 c = Class.forName(name, false, ClassLoader.getSystemClassLoader()); 158 } catch (ClassNotFoundException | RuntimeException | Error e) { 159 return trace(WARNING, e); 160 } 161 toolClasses.put(name, new WeakReference<>(c)); 162 } 163 return c.asSubclass(clazz); 164 } 165} 166