/* * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.tools; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; /** * Provides methods for locating tool providers, for example, * providers of compilers. This class complements the * functionality of {@link java.util.ServiceLoader}. * * @author Peter von der Ahé * @since 1.6 */ public class ToolProvider { private static final String systemJavaCompilerModule = "jdk.compiler"; private static final String systemJavaCompilerName = "com.sun.tools.javac.api.JavacTool"; /** * Returns the Java™ programming language compiler provided * with this platform. *

The file manager returned by calling * {@link JavaCompiler#getStandardFileManager getStandardFileManager} * on this compiler supports paths provided by any * {@linkplain java.nio.file.FileSystem filesystem}.

* @return the compiler provided with this platform or * {@code null} if no compiler is provided * @implNote This implementation returns the compiler provided * by the {@code jdk.compiler} module if that module is available, * and null otherwise. */ public static JavaCompiler getSystemJavaCompiler() { return getSystemTool(JavaCompiler.class, systemJavaCompilerModule, systemJavaCompilerName); } private static final String systemDocumentationToolModule = "jdk.javadoc"; private static final String systemDocumentationToolName = "jdk.javadoc.internal.api.JavadocTool"; /** * Returns the Java™ programming language documentation tool provided * with this platform. *

The file manager returned by calling * {@link DocumentationTool#getStandardFileManager getStandardFileManager} * on this tool supports paths provided by any * {@linkplain java.nio.file.FileSystem filesystem}.

* @return the documentation tool provided with this platform or * {@code null} if no documentation tool is provided * @implNote This implementation returns the tool provided * by the {@code jdk.javadoc} module if that module is available, * and null otherwise. */ public static DocumentationTool getSystemDocumentationTool() { return getSystemTool(DocumentationTool.class, systemDocumentationToolModule, systemDocumentationToolName); } /** * Returns the class loader for tools provided with this platform. * This does not include user-installed tools. Use the * {@linkplain java.util.ServiceLoader service provider mechanism} * for locating user installed tools. * * @return the class loader for tools provided with this platform * or {@code null} if no tools are provided */ public static ClassLoader getSystemToolClassLoader() { return ClassLoader.getSystemClassLoader(); } private static final boolean useLegacy; static { Class c = null; try { c = Class.forName("java.lang.reflect.Module"); } catch (Throwable t) { } useLegacy = (c == null); } /** * Get an instance of a system tool using the service loader. * @implNote By default, this returns the implementation in the specified module. * For limited backward compatibility, if this code is run on an older version * of the Java platform that does not support modules, this method will * try and create an instance of the named class. Note that implies the * class must be available on the system class path. * @param the interface of the tool * @param clazz the interface of the tool * @param moduleName the name of the module containing the desired implementation * @param className the class name of the desired implementation * @return the specified implementation of the tool */ private static T getSystemTool(Class clazz, String moduleName, String className) { if (useLegacy) { try { @SuppressWarnings("deprecation") T result = Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance(); return result; } catch (ReflectiveOperationException e) { throw new Error(e); } } try { ServiceLoader sl = ServiceLoader.load(clazz, ClassLoader.getSystemClassLoader()); for (Iterator iter = sl.iterator(); iter.hasNext(); ) { T tool = iter.next(); if (matches(tool, moduleName)) return tool; } } catch (ServiceConfigurationError e) { throw new Error(e); } return null; } /** * Determine if this is tho desired tool instance. * @param the interface of the tool * @param tool the instance of the tool * @param moduleName the name of the module containing the desired implementation * @return true if and only if the tool matches the specified criteria */ private static boolean matches(T tool, String moduleName) { // for now, use reflection to implement // return moduleName.equals(tool.getClass().getModule().getName()); try { Method getModuleMethod = Class.class.getDeclaredMethod("getModule"); Object toolModule = getModuleMethod.invoke(tool.getClass()); Method getNameMethod = toolModule.getClass().getDeclaredMethod("getName"); String toolModuleName = (String) getNameMethod.invoke(toolModule); return moduleName.equals(toolModuleName); } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { return false; } } }