Tue, 28 Dec 2010 15:54:52 -0800
6962318: Update copyright year
Reviewed-by: xdono
1 /*
2 * Copyright (c) 2005, 2010, 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 */
26 package javax.tools;
28 import java.io.File;
29 import java.lang.ref.Reference;
30 import java.lang.ref.WeakReference;
31 import java.net.URL;
32 import java.net.URLClassLoader;
33 import java.net.MalformedURLException;
34 import java.util.HashMap;
35 import java.util.Locale;
36 import java.util.Map;
37 import java.util.logging.Logger;
38 import java.util.logging.Level;
39 import static java.util.logging.Level.*;
41 /**
42 * Provides methods for locating tool providers, for example,
43 * providers of compilers. This class complements the
44 * functionality of {@link java.util.ServiceLoader}.
45 *
46 * @author Peter von der Ahé
47 * @since 1.6
48 */
49 public class ToolProvider {
51 private static final String propertyName = "sun.tools.ToolProvider";
52 private static final String loggerName = "javax.tools";
54 /*
55 * Define the system property "sun.tools.ToolProvider" to enable
56 * debugging:
57 *
58 * java ... -Dsun.tools.ToolProvider ...
59 */
60 static <T> T trace(Level level, Object reason) {
61 // NOTE: do not make this method private as it affects stack traces
62 try {
63 if (System.getProperty(propertyName) != null) {
64 StackTraceElement[] st = Thread.currentThread().getStackTrace();
65 String method = "???";
66 String cls = ToolProvider.class.getName();
67 if (st.length > 2) {
68 StackTraceElement frame = st[2];
69 method = String.format((Locale)null, "%s(%s:%s)",
70 frame.getMethodName(),
71 frame.getFileName(),
72 frame.getLineNumber());
73 cls = frame.getClassName();
74 }
75 Logger logger = Logger.getLogger(loggerName);
76 if (reason instanceof Throwable) {
77 logger.logp(level, cls, method,
78 reason.getClass().getName(), (Throwable)reason);
79 } else {
80 logger.logp(level, cls, method, String.valueOf(reason));
81 }
82 }
83 } catch (SecurityException ex) {
84 System.err.format((Locale)null, "%s: %s; %s%n",
85 ToolProvider.class.getName(),
86 reason,
87 ex.getLocalizedMessage());
88 }
89 return null;
90 }
92 private static final String defaultJavaCompilerName
93 = "com.sun.tools.javac.api.JavacTool";
95 /**
96 * Gets the Java™ programming language compiler provided
97 * with this platform.
98 * @return the compiler provided with this platform or
99 * {@code null} if no compiler is provided
100 */
101 public static JavaCompiler getSystemJavaCompiler() {
102 return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName);
103 }
105 /**
106 * Returns the class loader for tools provided with this platform.
107 * This does not include user-installed tools. Use the
108 * {@linkplain java.util.ServiceLoader service provider mechanism}
109 * for locating user installed tools.
110 *
111 * @return the class loader for tools provided with this platform
112 * or {@code null} if no tools are provided
113 */
114 public static ClassLoader getSystemToolClassLoader() {
115 try {
116 Class<? extends JavaCompiler> c =
117 instance().getSystemToolClass(JavaCompiler.class, defaultJavaCompilerName);
118 return c.getClassLoader();
119 } catch (Throwable e) {
120 return trace(WARNING, e);
121 }
122 }
125 private static ToolProvider instance;
127 private static synchronized ToolProvider instance() {
128 if (instance == null)
129 instance = new ToolProvider();
130 return instance;
131 }
133 // Cache for tool classes.
134 // Use weak references to avoid keeping classes around unnecessarily
135 private Map<String, Reference<Class<?>>> toolClasses = new HashMap<String, Reference<Class<?>>>();
137 // Cache for tool classloader.
138 // Use a weak reference to avoid keeping it around unnecessarily
139 private Reference<ClassLoader> refToolClassLoader = null;
142 private ToolProvider() { }
144 private <T> T getSystemTool(Class<T> clazz, String name) {
145 Class<? extends T> c = getSystemToolClass(clazz, name);
146 try {
147 return c.asSubclass(clazz).newInstance();
148 } catch (Throwable e) {
149 trace(WARNING, e);
150 return null;
151 }
152 }
154 private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) {
155 Reference<Class<?>> refClass = toolClasses.get(name);
156 Class<?> c = (refClass == null ? null : refClass.get());
157 if (c == null) {
158 try {
159 c = findSystemToolClass(name);
160 } catch (Throwable e) {
161 return trace(WARNING, e);
162 }
163 toolClasses.put(name, new WeakReference<Class<?>>(c));
164 }
165 return c.asSubclass(clazz);
166 }
168 private static final String[] defaultToolsLocation = { "lib", "tools.jar" };
170 private Class<?> findSystemToolClass(String toolClassName)
171 throws MalformedURLException, ClassNotFoundException
172 {
173 // try loading class directly, in case tool is on the bootclasspath
174 try {
175 return enableAsserts(Class.forName(toolClassName, false, null));
176 } catch (ClassNotFoundException e) {
177 trace(FINE, e);
179 // if tool not on bootclasspath, look in default tools location (tools.jar)
180 ClassLoader cl = (refToolClassLoader == null ? null : refToolClassLoader.get());
181 if (cl == null) {
182 File file = new File(System.getProperty("java.home"));
183 if (file.getName().equalsIgnoreCase("jre"))
184 file = file.getParentFile();
185 for (String name : defaultToolsLocation)
186 file = new File(file, name);
188 // if tools not found, no point in trying a URLClassLoader
189 // so rethrow the original exception.
190 if (!file.exists())
191 throw e;
193 URL[] urls = { file.toURI().toURL() };
194 trace(FINE, urls[0].toString());
196 cl = URLClassLoader.newInstance(urls);
197 cl.setPackageAssertionStatus("com.sun.tools.javac", true);
198 refToolClassLoader = new WeakReference<ClassLoader>(cl);
199 }
201 return Class.forName(toolClassName, false, cl);
202 }
204 }
206 private static Class<?> enableAsserts(Class<?> cls) {
207 try {
208 ClassLoader loader = cls.getClassLoader();
209 if (loader != null)
210 loader.setPackageAssertionStatus("com.sun.tools.javac", true);
211 else
212 trace(FINE, "loader == null");
213 } catch (SecurityException ex) {
214 trace(FINE, ex);
215 }
216 return cls;
217 }
220 }