1. /*
  2. * Copyright 2002-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.util;
  18. import java.io.File;
  19. import java.util.Vector;
  20. import org.apache.tools.ant.taskdefs.condition.Os;
  21. /**
  22. * A set of helper methods related to locating executables or checking
  23. * conditons of a given Java installation.
  24. *
  25. *
  26. * @since Ant 1.5
  27. */
  28. public class JavaEnvUtils {
  29. /** Are we on a DOS-based system */
  30. private static final boolean isDos = Os.isFamily("dos");
  31. /** Are we on Novell NetWare */
  32. private static final boolean isNetware = Os.isName("netware");
  33. /** Are we on AIX */
  34. private static final boolean isAix = Os.isName("aix");
  35. /** shortcut for System.getProperty("java.home") */
  36. private static final String javaHome = System.getProperty("java.home");
  37. /** FileUtils instance for path normalization */
  38. private static final FileUtils fileUtils = FileUtils.newFileUtils();
  39. /** Version of currently running VM. */
  40. private static String javaVersion;
  41. /** floating version of the JVM */
  42. private static int javaVersionNumber;
  43. /** Version constant for Java 1.0 */
  44. public static final String JAVA_1_0 = "1.0";
  45. /** Version constant for Java 1.1 */
  46. public static final String JAVA_1_1 = "1.1";
  47. /** Version constant for Java 1.2 */
  48. public static final String JAVA_1_2 = "1.2";
  49. /** Version constant for Java 1.3 */
  50. public static final String JAVA_1_3 = "1.3";
  51. /** Version constant for Java 1.4 */
  52. public static final String JAVA_1_4 = "1.4";
  53. /** Version constant for Java 1.5 */
  54. public static final String JAVA_1_5 = "1.5";
  55. /** array of packages in the runtime */
  56. private static Vector jrePackages;
  57. static {
  58. // Determine the Java version by looking at available classes
  59. // java.lang.Readable was introduced in JDK 1.5
  60. // java.lang.CharSequence was introduced in JDK 1.4
  61. // java.lang.StrictMath was introduced in JDK 1.3
  62. // java.lang.ThreadLocal was introduced in JDK 1.2
  63. // java.lang.Void was introduced in JDK 1.1
  64. // Count up version until a NoClassDefFoundError ends the try
  65. try {
  66. javaVersion = JAVA_1_0;
  67. javaVersionNumber = 10;
  68. Class.forName("java.lang.Void");
  69. javaVersion = JAVA_1_1;
  70. javaVersionNumber++;
  71. Class.forName("java.lang.ThreadLocal");
  72. javaVersion = JAVA_1_2;
  73. javaVersionNumber++;
  74. Class.forName("java.lang.StrictMath");
  75. javaVersion = JAVA_1_3;
  76. javaVersionNumber++;
  77. Class.forName("java.lang.CharSequence");
  78. javaVersion = JAVA_1_4;
  79. javaVersionNumber++;
  80. Class.forName("java.lang.Readable");
  81. javaVersion = JAVA_1_5;
  82. javaVersionNumber++;
  83. } catch (Throwable t) {
  84. // swallow as we've hit the max class version that
  85. // we have
  86. }
  87. }
  88. /**
  89. * Returns the version of Java this class is running under.
  90. * @return the version of Java as a String, e.g. "1.1"
  91. */
  92. public static String getJavaVersion() {
  93. return javaVersion;
  94. }
  95. /**
  96. * Compares the current Java version to the passed in String -
  97. * assumes the argument is one of the constants defined in this
  98. * class.
  99. * @return true if the version of Java is the same as the given
  100. * version.
  101. * @since Ant 1.5
  102. */
  103. public static boolean isJavaVersion(String version) {
  104. return javaVersion == version;
  105. }
  106. /**
  107. * Finds an executable that is part of a JRE installation based on
  108. * the java.home system property.
  109. *
  110. * <p><code>java</code>, <code>keytool</code>,
  111. * <code>policytool</code>, <code>orbd</code>, <code>rmid</code>,
  112. * <code>rmiregistry</code>, <code>servertool</code> and
  113. * <code>tnameserv</code> are JRE executables on Sun based
  114. * JRE's.</p>
  115. *
  116. * <p>You typically find them in <code>JAVA_HOME/jre/bin</code> if
  117. * <code>JAVA_HOME</code> points to your JDK installation. JDK
  118. * < 1.2 has them in the same directory as the JDK
  119. * executables.</p>
  120. *
  121. * @since Ant 1.5
  122. */
  123. public static String getJreExecutable(String command) {
  124. if (isNetware) {
  125. // Extrapolating from:
  126. // "NetWare may have a "java" in that directory, but 99% of
  127. // the time, you don't want to execute it" -- Jeff Tulley
  128. // <JTULLEY@novell.com>
  129. return command;
  130. }
  131. File jExecutable = null;
  132. if (isAix) {
  133. // On IBM's JDK 1.2 the directory layout is different, 1.3 follows
  134. // Sun's layout.
  135. jExecutable = findInDir(javaHome + "/sh", command);
  136. }
  137. if (jExecutable == null) {
  138. jExecutable = findInDir(javaHome + "/bin", command);
  139. }
  140. if (jExecutable != null) {
  141. return jExecutable.getAbsolutePath();
  142. } else {
  143. // Unfortunately on Windows java.home doesn't always refer
  144. // to the correct location, so we need to fall back to
  145. // assuming java is somewhere on the PATH.
  146. return addExtension(command);
  147. }
  148. }
  149. /**
  150. * Finds an executable that is part of a JDK installation based on
  151. * the java.home system property.
  152. *
  153. * <p>You typically find them in <code>JAVA_HOME/bin</code> if
  154. * <code>JAVA_HOME</code> points to your JDK installation.</p>
  155. *
  156. * @since Ant 1.5
  157. */
  158. public static String getJdkExecutable(String command) {
  159. if (isNetware) {
  160. // Extrapolating from:
  161. // "NetWare may have a "java" in that directory, but 99% of
  162. // the time, you don't want to execute it" -- Jeff Tulley
  163. // <JTULLEY@novell.com>
  164. return command;
  165. }
  166. File jExecutable = null;
  167. if (isAix) {
  168. // On IBM's JDK 1.2 the directory layout is different, 1.3 follows
  169. // Sun's layout.
  170. jExecutable = findInDir(javaHome + "/../sh", command);
  171. }
  172. if (jExecutable == null) {
  173. jExecutable = findInDir(javaHome + "/../bin", command);
  174. }
  175. if (jExecutable != null) {
  176. return jExecutable.getAbsolutePath();
  177. } else {
  178. // fall back to JRE bin directory, also catches JDK 1.0 and 1.1
  179. // where java.home points to the root of the JDK and Mac OS X where
  180. // the whole directory layout is different from Sun's
  181. return getJreExecutable(command);
  182. }
  183. }
  184. /**
  185. * Adds a system specific extension to the name of an executable.
  186. *
  187. * @since Ant 1.5
  188. */
  189. private static String addExtension(String command) {
  190. // This is the most common extension case - exe for windows and OS/2,
  191. // nothing for *nix.
  192. return command + (isDos ? ".exe" : "");
  193. }
  194. /**
  195. * Look for an executable in a given directory.
  196. *
  197. * @return null if the executable cannot be found.
  198. */
  199. private static File findInDir(String dirName, String commandName) {
  200. File dir = fileUtils.normalize(dirName);
  201. File executable = null;
  202. if (dir.exists()) {
  203. executable = new File(dir, addExtension(commandName));
  204. if (!executable.exists()) {
  205. executable = null;
  206. }
  207. }
  208. return executable;
  209. }
  210. /**
  211. * demand creation of the package list.
  212. * When you add a new package, add a new test below
  213. */
  214. private static void buildJrePackages() {
  215. jrePackages = new Vector();
  216. switch(javaVersionNumber) {
  217. case 15:
  218. case 14:
  219. jrePackages.addElement("org.apache.crimson");
  220. jrePackages.addElement("org.apache.xalan");
  221. jrePackages.addElement("org.apache.xml");
  222. jrePackages.addElement("org.apache.xpath");
  223. jrePackages.addElement("org.ietf.jgss");
  224. jrePackages.addElement("org.w3c.dom");
  225. jrePackages.addElement("org.xml.sax");
  226. // fall through
  227. case 13:
  228. jrePackages.addElement("org.omg");
  229. jrePackages.addElement("com.sun.corba");
  230. jrePackages.addElement("com.sun.jndi");
  231. jrePackages.addElement("com.sun.media");
  232. jrePackages.addElement("com.sun.naming");
  233. jrePackages.addElement("com.sun.org.omg");
  234. jrePackages.addElement("com.sun.rmi");
  235. jrePackages.addElement("sunw.io");
  236. jrePackages.addElement("sunw.util");
  237. // fall through
  238. case 12:
  239. jrePackages.addElement("com.sun.java");
  240. jrePackages.addElement("com.sun.image");
  241. // are there any here that we forgot?
  242. // fall through
  243. case 11:
  244. default:
  245. //things like sun.reflection, sun.misc, sun.net
  246. jrePackages.addElement("sun");
  247. jrePackages.addElement("java");
  248. jrePackages.addElement("javax");
  249. break;
  250. }
  251. }
  252. /**
  253. * Testing helper method; kept here for unification of changes.
  254. */
  255. public static Vector getJrePackageTestCases() {
  256. Vector tests = new Vector();
  257. tests.addElement("java.lang.Object");
  258. switch(javaVersionNumber) {
  259. case 15:
  260. case 14:
  261. tests.addElement("sun.audio.AudioPlayer");
  262. tests.addElement("org.apache.crimson.parser.ContentModel");
  263. tests.addElement("org.apache.xalan.processor.ProcessorImport");
  264. tests.addElement("org.apache.xml.utils.URI");
  265. tests.addElement("org.apache.xpath.XPathFactory");
  266. tests.addElement("org.ietf.jgss.Oid");
  267. tests.addElement("org.w3c.dom.Attr");
  268. tests.addElement("org.xml.sax.XMLReader");
  269. // fall through
  270. case 13:
  271. tests.addElement("org.omg.CORBA.Any");
  272. tests.addElement("com.sun.corba.se.internal.corba.AnyImpl");
  273. tests.addElement("com.sun.jndi.ldap.LdapURL");
  274. tests.addElement("com.sun.media.sound.Printer");
  275. tests.addElement("com.sun.naming.internal.VersionHelper");
  276. tests.addElement("com.sun.org.omg.CORBA.Initializer");
  277. tests.addElement("sunw.io.Serializable");
  278. tests.addElement("sunw.util.EventListener");
  279. // fall through
  280. case 12:
  281. tests.addElement("javax.accessibility.Accessible");
  282. tests.addElement("sun.misc.BASE64Encoder");
  283. tests.addElement("com.sun.image.codec.jpeg.JPEGCodec");
  284. // fall through
  285. case 11:
  286. default:
  287. //things like sun.reflection, sun.misc, sun.net
  288. tests.addElement("sun.reflect.SerializationConstructorAccessorImpl");
  289. tests.addElement("sun.net.www.http.HttpClient");
  290. tests.addElement("sun.audio.AudioPlayer");
  291. break;
  292. }
  293. return tests;
  294. }
  295. /**
  296. * get a vector of strings of packages built into
  297. * that platforms runtime jar(s)
  298. * @return list of packages
  299. */
  300. public static Vector getJrePackages() {
  301. if (jrePackages == null) {
  302. buildJrePackages();
  303. }
  304. return jrePackages;
  305. }
  306. }