1. /*
  2. * Copyright 2003-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.launch;
  18. import java.net.MalformedURLException;
  19. import java.net.URL;
  20. import java.io.File;
  21. import java.io.FilenameFilter;
  22. import java.text.CharacterIterator;
  23. import java.text.StringCharacterIterator;
  24. import java.util.Locale;
  25. /**
  26. * The Locator is a utility class which is used to find certain items
  27. * in the environment
  28. *
  29. * @since Ant 1.6
  30. */
  31. public final class Locator {
  32. /**
  33. * Not instantiable
  34. */
  35. private Locator() {
  36. }
  37. /**
  38. * Find the directory or jar file the class has been loaded from.
  39. *
  40. * @param c the class whose location is required.
  41. * @return the file or jar with the class or null if we cannot
  42. * determine the location.
  43. *
  44. * @since Ant 1.6
  45. */
  46. public static File getClassSource(Class c) {
  47. String classResource = c.getName().replace('.', '/') + ".class";
  48. return getResourceSource(c.getClassLoader(), classResource);
  49. }
  50. /**
  51. * Find the directory or jar a give resource has been loaded from.
  52. *
  53. * @param c the classloader to be consulted for the source
  54. * @param resource the resource whose location is required.
  55. *
  56. * @return the file with the resource source or null if
  57. * we cannot determine the location.
  58. *
  59. * @since Ant 1.6
  60. */
  61. public static File getResourceSource(ClassLoader c, String resource) {
  62. if (c == null) {
  63. c = Locator.class.getClassLoader();
  64. }
  65. URL url = null;
  66. if (c == null) {
  67. url = ClassLoader.getSystemResource(resource);
  68. } else {
  69. url = c.getResource(resource);
  70. }
  71. if (url != null) {
  72. String u = url.toString();
  73. if (u.startsWith("jar:file:")) {
  74. int pling = u.indexOf("!");
  75. String jarName = u.substring(4, pling);
  76. return new File(fromURI(jarName));
  77. } else if (u.startsWith("file:")) {
  78. int tail = u.indexOf(resource);
  79. String dirName = u.substring(0, tail);
  80. return new File(fromURI(dirName));
  81. }
  82. }
  83. return null;
  84. }
  85. /**
  86. * Constructs a file path from a <code>file:</code> URI.
  87. *
  88. * <p>Will be an absolute path if the given URI is absolute.</p>
  89. *
  90. * <p>Swallows '%' that are not followed by two characters,
  91. * doesn't deal with non-ASCII characters.</p>
  92. *
  93. * @param uri the URI designating a file in the local filesystem.
  94. * @return the local file system path for the file.
  95. * @since Ant 1.6
  96. */
  97. public static String fromURI(String uri) {
  98. URL url = null;
  99. try {
  100. url = new URL(uri);
  101. } catch (MalformedURLException emYouEarlEx) {
  102. }
  103. if (url == null || !("file".equals(url.getProtocol()))) {
  104. throw new IllegalArgumentException("Can only handle valid file: URIs");
  105. }
  106. StringBuffer buf = new StringBuffer(url.getHost());
  107. if (buf.length() > 0) {
  108. buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
  109. }
  110. String file = url.getFile();
  111. int queryPos = file.indexOf('?');
  112. buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
  113. uri = buf.toString().replace('/', File.separatorChar);
  114. if (File.pathSeparatorChar == ';' && uri.startsWith("\\") && uri.length() > 2
  115. && Character.isLetter(uri.charAt(1)) && uri.lastIndexOf(':') > -1) {
  116. uri = uri.substring(1);
  117. }
  118. StringBuffer sb = new StringBuffer();
  119. CharacterIterator iter = new StringCharacterIterator(uri);
  120. for (char c = iter.first(); c != CharacterIterator.DONE;
  121. c = iter.next()) {
  122. if (c == '%') {
  123. char c1 = iter.next();
  124. if (c1 != CharacterIterator.DONE) {
  125. int i1 = Character.digit(c1, 16);
  126. char c2 = iter.next();
  127. if (c2 != CharacterIterator.DONE) {
  128. int i2 = Character.digit(c2, 16);
  129. sb.append((char) ((i1 << 4) + i2));
  130. }
  131. }
  132. } else {
  133. sb.append(c);
  134. }
  135. }
  136. String path = sb.toString();
  137. return path;
  138. }
  139. /**
  140. * Get the File necessary to load the Sun compiler tools. If the classes
  141. * are available to this class, then no additional URL is required and
  142. * null is returned. This may be because the classes are explicitly in the
  143. * class path or provided by the JVM directly
  144. *
  145. * @return the tools jar as a File if required, null otherwise
  146. */
  147. public static File getToolsJar() {
  148. // firstly check if the tools jar is already in the classpath
  149. boolean toolsJarAvailable = false;
  150. try {
  151. // just check whether this throws an exception
  152. Class.forName("com.sun.tools.javac.Main");
  153. toolsJarAvailable = true;
  154. } catch (Exception e) {
  155. try {
  156. Class.forName("sun.tools.javac.Main");
  157. toolsJarAvailable = true;
  158. } catch (Exception e2) {
  159. // ignore
  160. }
  161. }
  162. if (toolsJarAvailable) {
  163. return null;
  164. }
  165. // couldn't find compiler - try to find tools.jar
  166. // based on java.home setting
  167. String javaHome = System.getProperty("java.home");
  168. if (javaHome.toLowerCase(Locale.US).endsWith("jre")) {
  169. javaHome = javaHome.substring(0, javaHome.length() - 4);
  170. }
  171. File toolsJar = new File(javaHome + "/lib/tools.jar");
  172. if (!toolsJar.exists()) {
  173. System.out.println("Unable to locate tools.jar. "
  174. + "Expected to find it in " + toolsJar.getPath());
  175. return null;
  176. }
  177. return toolsJar;
  178. }
  179. /**
  180. * Get an array or URLs representing all of the jar files in the
  181. * given location. If the location is a file, it is returned as the only
  182. * element of the array. If the location is a directory, it is scanned for
  183. * jar files
  184. *
  185. * @param location the location to scan for Jars
  186. *
  187. * @return an array of URLs for all jars in the given location.
  188. *
  189. * @exception MalformedURLException if the URLs for the jars cannot be
  190. * formed
  191. */
  192. public static URL[] getLocationURLs(File location)
  193. throws MalformedURLException {
  194. return getLocationURLs(location, new String[]{".jar"});
  195. }
  196. /**
  197. * Get an array or URLs representing all of the files of a given set of
  198. * extensions in the given location. If the location is a file, it is
  199. * returned as the only element of the array. If the location is a
  200. * directory, it is scanned for matching files
  201. *
  202. * @param location the location to scan for files
  203. * @param extensions an array of extension that are to match in the
  204. * directory search
  205. *
  206. * @return an array of URLs of matching files
  207. * @exception MalformedURLException if the URLs for the files cannot be
  208. * formed
  209. */
  210. public static URL[] getLocationURLs(File location,
  211. final String[] extensions)
  212. throws MalformedURLException {
  213. URL[] urls = new URL[0];
  214. if (!location.exists()) {
  215. return urls;
  216. }
  217. if (!location.isDirectory()) {
  218. urls = new URL[1];
  219. String path = location.getPath();
  220. for (int i = 0; i < extensions.length; ++i) {
  221. if (path.toLowerCase().endsWith(extensions[i])) {
  222. urls[0] = location.toURL();
  223. break;
  224. }
  225. }
  226. return urls;
  227. }
  228. File[] matches = location.listFiles(
  229. new FilenameFilter() {
  230. public boolean accept(File dir, String name) {
  231. for (int i = 0; i < extensions.length; ++i) {
  232. if (name.toLowerCase().endsWith(extensions[i])) {
  233. return true;
  234. }
  235. }
  236. return false;
  237. }
  238. });
  239. urls = new URL[matches.length];
  240. for (int i = 0; i < matches.length; ++i) {
  241. urls[i] = matches[i].toURL();
  242. }
  243. return urls;
  244. }
  245. }