ToolProvider.java revision 4104:4012b3f11f0d
1/* 2 * Copyright (c) 2005, 2016, 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.reflect.InvocationTargetException; 29import java.lang.reflect.Method; 30import java.security.AccessController; 31import java.security.PrivilegedAction; 32import java.util.Iterator; 33import java.util.ServiceConfigurationError; 34import java.util.ServiceLoader; 35 36/** 37 * Provides methods for locating tool providers, for example, 38 * providers of compilers. This class complements the 39 * functionality of {@link java.util.ServiceLoader}. 40 * 41 * @author Peter von der Ahé 42 * @since 1.6 43 */ 44public class ToolProvider { 45 46 private static final String systemJavaCompilerModule = "jdk.compiler"; 47 private static final String systemJavaCompilerName = "com.sun.tools.javac.api.JavacTool"; 48 49 /** 50 * Returns the Java™ programming language compiler provided 51 * with this platform. 52 * <p>The file manager returned by calling 53 * {@link JavaCompiler#getStandardFileManager getStandardFileManager} 54 * on this compiler supports paths provided by any 55 * {@linkplain java.nio.file.FileSystem filesystem}.</p> 56 * @return the compiler provided with this platform or 57 * {@code null} if no compiler is provided 58 * @implNote This implementation returns the compiler provided 59 * by the {@code jdk.compiler} module if that module is available, 60 * and {@code null} otherwise. 61 */ 62 public static JavaCompiler getSystemJavaCompiler() { 63 return getSystemTool(JavaCompiler.class, 64 systemJavaCompilerModule, systemJavaCompilerName); 65 } 66 67 private static final String systemDocumentationToolModule = "jdk.javadoc"; 68 private static final String systemDocumentationToolName = "jdk.javadoc.internal.api.JavadocTool"; 69 70 /** 71 * Returns the Java™ programming language documentation tool provided 72 * with this platform. 73 * <p>The file manager returned by calling 74 * {@link DocumentationTool#getStandardFileManager getStandardFileManager} 75 * on this tool supports paths provided by any 76 * {@linkplain java.nio.file.FileSystem filesystem}.</p> 77 * @return the documentation tool provided with this platform or 78 * {@code null} if no documentation tool is provided 79 * @implNote This implementation returns the tool provided 80 * by the {@code jdk.javadoc} module if that module is available, 81 * and {@code null} otherwise. 82 */ 83 public static DocumentationTool getSystemDocumentationTool() { 84 return getSystemTool(DocumentationTool.class, 85 systemDocumentationToolModule, systemDocumentationToolName); 86 } 87 88 /** 89 * Returns a class loader that may be used to load system tools, 90 * or {@code null} if no such special loader is provided. 91 * @implSpec This implementation always returns {@code null}. 92 * @deprecated This method is subject to removal in a future version of 93 * Java SE. 94 * Use the {@link java.util.spi.ToolProvider system tool provider} or 95 * {@link java.util.ServiceLoader service loader} mechanisms to 96 * locate system tools as well as user-installed tools. 97 * @return a class loader, or {@code null} 98 */ 99 @Deprecated 100 public static ClassLoader getSystemToolClassLoader() { 101 return null; 102 } 103 104 private static final boolean useLegacy; 105 106 static { 107 Class<?> c = null; 108 try { 109 c = Class.forName("java.lang.Module"); 110 } catch (Throwable t) { 111 } 112 useLegacy = (c == null); 113 } 114 115 /** 116 * Get an instance of a system tool using the service loader. 117 * @implNote By default, this returns the implementation in the specified module. 118 * For limited backward compatibility, if this code is run on an older version 119 * of the Java platform that does not support modules, this method will 120 * try and create an instance of the named class. Note that implies the 121 * class must be available on the system class path. 122 * @param <T> the interface of the tool 123 * @param clazz the interface of the tool 124 * @param moduleName the name of the module containing the desired implementation 125 * @param className the class name of the desired implementation 126 * @return the specified implementation of the tool 127 */ 128 private static <T> T getSystemTool(Class<T> clazz, String moduleName, String className) { 129 if (useLegacy) { 130 try { 131 return Class.forName(className, true, ClassLoader.getSystemClassLoader()). 132 asSubclass(clazz).getConstructor().newInstance(); 133 } catch (ReflectiveOperationException e) { 134 throw new Error(e); 135 } 136 } 137 138 try { 139 ServiceLoader<T> sl = ServiceLoader.load(clazz, ClassLoader.getSystemClassLoader()); 140 for (Iterator<T> iter = sl.iterator(); iter.hasNext(); ) { 141 T tool = iter.next(); 142 if (matches(tool, moduleName)) 143 return tool; 144 } 145 } catch (ServiceConfigurationError e) { 146 throw new Error(e); 147 } 148 return null; 149 } 150 151 /** 152 * Determine if this is the desired tool instance. 153 * @param <T> the interface of the tool 154 * @param tool the instance of the tool 155 * @param moduleName the name of the module containing the desired implementation 156 * @return true if and only if the tool matches the specified criteria 157 */ 158 private static <T> boolean matches(T tool, String moduleName) { 159 PrivilegedAction<Boolean> pa = () -> { 160 // for now, use reflection to implement 161 // return moduleName.equals(tool.getClass().getModule().getName()); 162 try { 163 Method getModuleMethod = Class.class.getDeclaredMethod("getModule"); 164 Object toolModule = getModuleMethod.invoke(tool.getClass()); 165 Method getNameMethod = toolModule.getClass().getDeclaredMethod("getName"); 166 String toolModuleName = (String) getNameMethod.invoke(toolModule); 167 return moduleName.equals(toolModuleName); 168 } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { 169 return false; 170 } 171 }; 172 return AccessController.doPrivileged(pa); 173 } 174} 175