ToolProvider.java revision 3779:7d2f8aa366e2
10Sduke/* 212897Svkempik * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 30Sduke * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 40Sduke * 50Sduke * This code is free software; you can redistribute it and/or modify it 60Sduke * under the terms of the GNU General Public License version 2 only, as 70Sduke * published by the Free Software Foundation. Oracle designates this 80Sduke * particular file as subject to the "Classpath" exception as provided 90Sduke * by Oracle in the LICENSE file that accompanied this code. 100Sduke * 110Sduke * This code is distributed in the hope that it will be useful, but WITHOUT 120Sduke * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 130Sduke * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 140Sduke * version 2 for more details (a copy is included in the LICENSE file that 150Sduke * accompanied this code). 160Sduke * 170Sduke * You should have received a copy of the GNU General Public License version 180Sduke * 2 along with this work; if not, write to the Free Software Foundation, 191472Strims * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201472Strims * 211472Strims * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 220Sduke * or visit www.oracle.com if you need additional information or have any 230Sduke * questions. 240Sduke */ 251879Sstefank 261879Sstefankpackage javax.tools; 271879Sstefank 2812546Srprotacioimport java.lang.reflect.InvocationTargetException; 291879Sstefankimport java.lang.reflect.Method; 301879Sstefankimport java.security.AccessController; 316760Sgoetzimport java.security.PrivilegedAction; 321879Sstefankimport java.util.Iterator; 331879Sstefankimport java.util.ServiceConfigurationError; 348413Splidenimport java.util.ServiceLoader; 351879Sstefank 369333Srprotacio/** 3713325Sstuefe * Provides methods for locating tool providers, for example, 381879Sstefank * providers of compilers. This class complements the 396591Sdsimms * functionality of {@link java.util.ServiceLoader}. 406591Sdsimms * 416591Sdsimms * @author Peter von der Ahé 4210762Sjprovino * @since 1.6 431879Sstefank */ 441879Sstefankpublic class ToolProvider { 451879Sstefank 461879Sstefank private static final String systemJavaCompilerModule = "jdk.compiler"; 471879Sstefank private static final String systemJavaCompilerName = "com.sun.tools.javac.api.JavacTool"; 4811857Sdholmes 491879Sstefank /** 501879Sstefank * Returns the Java™ programming language compiler provided 511879Sstefank * with this platform. 521879Sstefank * <p>The file manager returned by calling 531879Sstefank * {@link JavaCompiler#getStandardFileManager getStandardFileManager} 546683Sgoetz * on this compiler supports paths provided by any 551879Sstefank * {@linkplain java.nio.file.FileSystem filesystem}.</p> 563864Sstefank * @return the compiler provided with this platform or 576760Sgoetz * {@code null} if no compiler is provided 581879Sstefank * @implNote This implementation returns the compiler provided 597015Szgu * by the {@code jdk.compiler} module if that module is available, 603465Szgu * and {@code null} otherwise. 618413Spliden */ 621879Sstefank public static JavaCompiler getSystemJavaCompiler() { 6313249Sstefank return getSystemTool(JavaCompiler.class, 641879Sstefank systemJavaCompilerModule, systemJavaCompilerName); 651879Sstefank } 660Sduke 670Sduke private static final String systemDocumentationToolModule = "jdk.javadoc"; 6810627Sstuefe private static final String systemDocumentationToolName = "jdk.javadoc.internal.api.JavadocTool"; 690Sduke 700Sduke /** 710Sduke * Returns the Java™ programming language documentation tool provided 720Sduke * with this platform. 730Sduke * <p>The file manager returned by calling 7413211Scoleenp * {@link DocumentationTool#getStandardFileManager getStandardFileManager} 750Sduke * on this tool supports paths provided by any 7611659Stschatzl * {@linkplain java.nio.file.FileSystem filesystem}.</p> 770Sduke * @return the documentation tool provided with this platform or 780Sduke * {@code null} if no documentation tool is provided 790Sduke * @implNote This implementation returns the tool provided 802122Skvn * by the {@code jdk.javadoc} module if that module is available, 812122Skvn * and {@code null} otherwise. 822122Skvn */ 832122Skvn public static DocumentationTool getSystemDocumentationTool() { 840Sduke return getSystemTool(DocumentationTool.class, 850Sduke systemDocumentationToolModule, systemDocumentationToolName); 864367Srdurbin } 874367Srdurbin 882943Sphh /** 892943Sphh * Returns a class loader that may be used to load system tools, 902943Sphh * or {@code null} if no such special loader is provided. 912943Sphh * @implSpec This implementation always returns {@code null}. 922943Sphh * @deprecated This method is subject to removal in a future version of 932943Sphh * Java SE. 940Sduke * Use the {@link java.util.spi.ToolProvider system tool provider} or 950Sduke * {@link java.util.ServiceLoader service loader} mechanisms to 960Sduke * locate system tools as well as user-installed tools. 970Sduke * @return a class loader, or {@code null} 980Sduke */ 990Sduke @Deprecated 1000Sduke public static ClassLoader getSystemToolClassLoader() { 1010Sduke return null; 10212257Smlarsson } 1030Sduke 1040Sduke private static final boolean useLegacy; 1050Sduke 1069259Sgoetz static { 1070Sduke Class<?> c = null; 1080Sduke try { 1090Sduke c = Class.forName("java.lang.reflect.Module"); 1100Sduke } catch (Throwable t) { 1110Sduke } 1120Sduke useLegacy = (c == null); 1130Sduke } 1140Sduke 1150Sduke /** 1160Sduke * Get an instance of a system tool using the service loader. 1170Sduke * @implNote By default, this returns the implementation in the specified module. 1180Sduke * For limited backward compatibility, if this code is run on an older version 11961Ssbohne * of the Java platform that does not support modules, this method will 1200Sduke * try and create an instance of the named class. Note that implies the 1210Sduke * class must be available on the system class path. 1220Sduke * @param <T> the interface of the tool 1230Sduke * @param clazz the interface of the tool 1240Sduke * @param moduleName the name of the module containing the desired implementation 1250Sduke * @param className the class name of the desired implementation 126548Sysr * @return the specified implementation of the tool 12712257Smlarsson */ 12812257Smlarsson private static <T> T getSystemTool(Class<T> clazz, String moduleName, String className) { 12912257Smlarsson if (useLegacy) { 13012257Smlarsson try { 13112257Smlarsson return Class.forName(className, true, ClassLoader.getSystemClassLoader()). 13212257Smlarsson asSubclass(clazz).getConstructor().newInstance(); 13312257Smlarsson } catch (ReflectiveOperationException e) { 13412257Smlarsson throw new Error(e); 13512257Smlarsson } 13612257Smlarsson } 1370Sduke 1382721Snever try { 1392721Snever ServiceLoader<T> sl = ServiceLoader.load(clazz, ClassLoader.getSystemClassLoader()); 1402721Snever for (Iterator<T> iter = sl.iterator(); iter.hasNext(); ) { 1410Sduke T tool = iter.next(); 1422721Snever if (matches(tool, moduleName)) 1430Sduke return tool; 1440Sduke } 1450Sduke } catch (ServiceConfigurationError e) { 1460Sduke throw new Error(e); 1470Sduke } 1480Sduke return null; 1490Sduke } 1500Sduke 1510Sduke /** 1520Sduke * Determine if this is the desired tool instance. 15312257Smlarsson * @param <T> the interface of the tool 15412257Smlarsson * @param tool the instance of the tool 15512257Smlarsson * @param moduleName the name of the module containing the desired implementation 15612257Smlarsson * @return true if and only if the tool matches the specified criteria 15712257Smlarsson */ 15812257Smlarsson private static <T> boolean matches(T tool, String moduleName) { 1590Sduke PrivilegedAction<Boolean> pa = () -> { 160548Sysr // for now, use reflection to implement 1610Sduke // return moduleName.equals(tool.getClass().getModule().getName()); 1620Sduke try { 163548Sysr Method getModuleMethod = Class.class.getDeclaredMethod("getModule"); 1640Sduke Object toolModule = getModuleMethod.invoke(tool.getClass()); 1650Sduke Method getNameMethod = toolModule.getClass().getDeclaredMethod("getName"); 1660Sduke String toolModuleName = (String) getNameMethod.invoke(toolModule); 1670Sduke return moduleName.equals(toolModuleName); 1680Sduke } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { 1690Sduke return false; 1700Sduke } 1710Sduke }; 1720Sduke return AccessController.doPrivileged(pa); 1730Sduke } 1740Sduke} 1750Sduke