duke@1: /* ohair@554: * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package javax.tools; duke@1: duke@1: import java.io.File; duke@1: import java.net.URL; duke@1: import java.net.URLClassLoader; duke@1: import java.net.MalformedURLException; duke@1: import java.util.Locale; duke@1: import java.util.logging.Logger; duke@1: import java.util.logging.Level; duke@1: import static java.util.logging.Level.*; duke@1: duke@1: /** duke@1: * Provides methods for locating tool providers, for example, duke@1: * providers of compilers. This class complements the duke@1: * functionality of {@link java.util.ServiceLoader}. duke@1: * duke@1: * @author Peter von der Ahé duke@1: * @since 1.6 duke@1: */ duke@1: public class ToolProvider { duke@1: duke@1: private ToolProvider() {} duke@1: duke@1: private static final String propertyName = "sun.tools.ToolProvider"; duke@1: private static final String loggerName = "javax.tools"; duke@1: duke@1: /* duke@1: * Define the system property "sun.tools.ToolProvider" to enable duke@1: * debugging: duke@1: * duke@1: * java ... -Dsun.tools.ToolProvider ... duke@1: */ duke@1: static T trace(Level level, Object reason) { duke@1: // NOTE: do not make this method private as it affects stack traces duke@1: try { duke@1: if (System.getProperty(propertyName) != null) { duke@1: StackTraceElement[] st = Thread.currentThread().getStackTrace(); duke@1: String method = "???"; duke@1: String cls = ToolProvider.class.getName(); duke@1: if (st.length > 2) { duke@1: StackTraceElement frame = st[2]; duke@1: method = String.format((Locale)null, "%s(%s:%s)", duke@1: frame.getMethodName(), duke@1: frame.getFileName(), duke@1: frame.getLineNumber()); duke@1: cls = frame.getClassName(); duke@1: } duke@1: Logger logger = Logger.getLogger(loggerName); duke@1: if (reason instanceof Throwable) { duke@1: logger.logp(level, cls, method, duke@1: reason.getClass().getName(), (Throwable)reason); duke@1: } else { duke@1: logger.logp(level, cls, method, String.valueOf(reason)); duke@1: } duke@1: } duke@1: } catch (SecurityException ex) { duke@1: System.err.format((Locale)null, "%s: %s; %s%n", duke@1: ToolProvider.class.getName(), duke@1: reason, duke@1: ex.getLocalizedMessage()); duke@1: } duke@1: return null; duke@1: } duke@1: duke@1: /** duke@1: * Gets the Java™ programming language compiler provided duke@1: * with this platform. duke@1: * @return the compiler provided with this platform or duke@1: * {@code null} if no compiler is provided duke@1: */ duke@1: public static JavaCompiler getSystemJavaCompiler() { duke@1: if (Lazy.compilerClass == null) duke@1: return trace(WARNING, "Lazy.compilerClass == null"); duke@1: try { duke@1: return Lazy.compilerClass.newInstance(); duke@1: } catch (Throwable e) { duke@1: return trace(WARNING, e); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Returns the class loader for tools provided with this platform. duke@1: * This does not include user-installed tools. Use the duke@1: * {@linkplain java.util.ServiceLoader service provider mechanism} duke@1: * for locating user installed tools. duke@1: * duke@1: * @return the class loader for tools provided with this platform duke@1: * or {@code null} if no tools are provided duke@1: */ duke@1: public static ClassLoader getSystemToolClassLoader() { duke@1: if (Lazy.compilerClass == null) duke@1: return trace(WARNING, "Lazy.compilerClass == null"); duke@1: return Lazy.compilerClass.getClassLoader(); duke@1: } duke@1: duke@1: /** duke@1: * This class will not be initialized until one of the above duke@1: * methods are called. This ensures that searching for the duke@1: * compiler does not affect platform start up. duke@1: */ duke@1: static class Lazy { duke@1: private static final String defaultJavaCompilerName duke@1: = "com.sun.tools.javac.api.JavacTool"; duke@1: private static final String[] defaultToolsLocation duke@1: = { "lib", "tools.jar" }; duke@1: static final Class compilerClass; duke@1: static { duke@1: Class c = null; duke@1: try { duke@1: c = findClass().asSubclass(JavaCompiler.class); duke@1: } catch (Throwable t) { duke@1: trace(WARNING, t); duke@1: } duke@1: compilerClass = c; duke@1: } duke@1: duke@1: private static Class findClass() duke@1: throws MalformedURLException, ClassNotFoundException duke@1: { duke@1: try { duke@1: return enableAsserts(Class.forName(defaultJavaCompilerName, false, null)); duke@1: } catch (ClassNotFoundException e) { duke@1: trace(FINE, e); duke@1: } duke@1: File file = new File(System.getProperty("java.home")); duke@1: if (file.getName().equalsIgnoreCase("jre")) duke@1: file = file.getParentFile(); duke@1: for (String name : defaultToolsLocation) duke@1: file = new File(file, name); duke@1: URL[] urls = {file.toURI().toURL()}; duke@1: trace(FINE, urls[0].toString()); duke@1: ClassLoader cl = URLClassLoader.newInstance(urls); duke@1: cl.setPackageAssertionStatus("com.sun.tools.javac", true); duke@1: return Class.forName(defaultJavaCompilerName, false, cl); duke@1: } duke@1: duke@1: private static Class enableAsserts(Class cls) { duke@1: try { duke@1: ClassLoader loader = cls.getClassLoader(); duke@1: if (loader != null) duke@1: loader.setPackageAssertionStatus("com.sun.tools.javac", true); duke@1: else duke@1: trace(FINE, "loader == null"); duke@1: } catch (SecurityException ex) { duke@1: trace(FINE, ex); duke@1: } duke@1: return cls; duke@1: } duke@1: } duke@1: }