You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

JavaEnvUtils.java 17 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.util;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.io.FileWriter;
  22. import java.io.BufferedWriter;
  23. import java.util.Vector;
  24. import org.apache.tools.ant.taskdefs.condition.Os;
  25. /**
  26. * A set of helper methods related to locating executables or checking
  27. * conditons of a given Java installation.
  28. *
  29. * @since Ant 1.5
  30. */
  31. public final class JavaEnvUtils {
  32. private JavaEnvUtils() {
  33. }
  34. /** Are we on a DOS-based system */
  35. private static final boolean IS_DOS = Os.isFamily("dos");
  36. /** Are we on Novell NetWare */
  37. private static final boolean IS_NETWARE = Os.isName("netware");
  38. /** Are we on AIX */
  39. private static final boolean IS_AIX = Os.isName("aix");
  40. /** shortcut for System.getProperty("java.home") */
  41. private static final String JAVA_HOME = System.getProperty("java.home");
  42. /** FileUtils instance for path normalization */
  43. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  44. /** Version of currently running VM. */
  45. private static String javaVersion;
  46. /** floating version of the JVM */
  47. private static int javaVersionNumber;
  48. /** Version constant for Java 1.0 */
  49. public static final String JAVA_1_0 = "1.0";
  50. /** Number Version constant for Java 1.0 */
  51. public static final int VERSION_1_0 = 10;
  52. /** Version constant for Java 1.1 */
  53. public static final String JAVA_1_1 = "1.1";
  54. /** Number Version constant for Java 1.1 */
  55. public static final int VERSION_1_1 = 11;
  56. /** Version constant for Java 1.2 */
  57. public static final String JAVA_1_2 = "1.2";
  58. /** Number Version constant for Java 1.2 */
  59. public static final int VERSION_1_2 = 12;
  60. /** Version constant for Java 1.3 */
  61. public static final String JAVA_1_3 = "1.3";
  62. /** Number Version constant for Java 1.3 */
  63. public static final int VERSION_1_3 = 13;
  64. /** Version constant for Java 1.4 */
  65. public static final String JAVA_1_4 = "1.4";
  66. /** Number Version constant for Java 1.4 */
  67. public static final int VERSION_1_4 = 14;
  68. /** Version constant for Java 1.5 */
  69. public static final String JAVA_1_5 = "1.5";
  70. /** Number Version constant for Java 1.5 */
  71. public static final int VERSION_1_5 = 15;
  72. /** Version constant for Java 1.6 */
  73. public static final String JAVA_1_6 = "1.6";
  74. /** Number Version constant for Java 1.6 */
  75. public static final int VERSION_1_6 = 16;
  76. /** Whether this is the Kaffe VM */
  77. private static boolean kaffeDetected;
  78. /** array of packages in the runtime */
  79. private static Vector jrePackages;
  80. static {
  81. // Determine the Java version by looking at available classes
  82. // java.net.Proxy was introduced in JDK 1.5
  83. // java.lang.CharSequence was introduced in JDK 1.4
  84. // java.lang.StrictMath was introduced in JDK 1.3
  85. // java.lang.ThreadLocal was introduced in JDK 1.2
  86. // java.lang.Void was introduced in JDK 1.1
  87. // Count up version until a NoClassDefFoundError ends the try
  88. try {
  89. javaVersion = JAVA_1_0;
  90. javaVersionNumber = VERSION_1_0;
  91. Class.forName("java.lang.Void");
  92. javaVersion = JAVA_1_1;
  93. javaVersionNumber++;
  94. Class.forName("java.lang.ThreadLocal");
  95. javaVersion = JAVA_1_2;
  96. javaVersionNumber++;
  97. Class.forName("java.lang.StrictMath");
  98. javaVersion = JAVA_1_3;
  99. javaVersionNumber++;
  100. Class.forName("java.lang.CharSequence");
  101. javaVersion = JAVA_1_4;
  102. javaVersionNumber++;
  103. Class.forName("java.net.Proxy");
  104. javaVersion = JAVA_1_5;
  105. javaVersionNumber++;
  106. Class.forName("java.util.ServiceLoader");
  107. javaVersion = JAVA_1_6;
  108. javaVersionNumber++;
  109. } catch (Throwable t) {
  110. // swallow as we've hit the max class version that
  111. // we have
  112. }
  113. kaffeDetected = false;
  114. try {
  115. Class.forName("kaffe.util.NotImplemented");
  116. kaffeDetected = true;
  117. } catch (Throwable t) {
  118. // swallow as this simply doesn't seem to be Kaffe
  119. }
  120. }
  121. /**
  122. * Returns the version of Java this class is running under.
  123. * @return the version of Java as a String, e.g. "1.6"
  124. */
  125. public static String getJavaVersion() {
  126. return javaVersion;
  127. }
  128. /**
  129. * Returns the version of Java this class is running under.
  130. * This number can be used for comparisions; it will always be
  131. * @return the version of Java as a number 10x the major/minor,
  132. * e.g Java1.5 has a value of 15
  133. */
  134. public static int getJavaVersionNumber() {
  135. return javaVersionNumber;
  136. }
  137. /**
  138. * Compares the current Java version to the passed in String -
  139. * assumes the argument is one of the constants defined in this
  140. * class.
  141. * Note that Ant now requires JDK 1.4+ so {@link #JAVA_1_0} through
  142. * {@link #JAVA_1_3} need no longer be tested for.
  143. * @param version the version to check against the current version.
  144. * @return true if the version of Java is the same as the given version.
  145. * @since Ant 1.5
  146. */
  147. public static boolean isJavaVersion(String version) {
  148. return javaVersion.equals(version);
  149. }
  150. /**
  151. * Compares the current Java version to the passed in String -
  152. * assumes the argument is one of the constants defined in this
  153. * class.
  154. * Note that Ant now requires JDK 1.4+ so {@link #JAVA_1_0} through
  155. * {@link #JAVA_1_3} need no longer be tested for.
  156. * @param version the version to check against the current version.
  157. * @return true if the version of Java is the same or higher than the
  158. * given version.
  159. * @since Ant 1.7
  160. */
  161. public static boolean isAtLeastJavaVersion(String version) {
  162. return javaVersion.compareTo(version) >= 0;
  163. }
  164. /**
  165. * Checks whether the current Java VM is Kaffe.
  166. * @return true if the current Java VM is Kaffe.
  167. * @since Ant 1.6.3
  168. * @see <a href="http://www.kaffe.org/">http://www.kaffe.org/</a>
  169. */
  170. public static boolean isKaffe() {
  171. return kaffeDetected;
  172. }
  173. /**
  174. * Finds an executable that is part of a JRE installation based on
  175. * the java.home system property.
  176. *
  177. * <p><code>java</code>, <code>keytool</code>,
  178. * <code>policytool</code>, <code>orbd</code>, <code>rmid</code>,
  179. * <code>rmiregistry</code>, <code>servertool</code> and
  180. * <code>tnameserv</code> are JRE executables on Sun based
  181. * JRE's.</p>
  182. *
  183. * <p>You typically find them in <code>JAVA_HOME/jre/bin</code> if
  184. * <code>JAVA_HOME</code> points to your JDK installation. JDK
  185. * &lt; 1.2 has them in the same directory as the JDK
  186. * executables.</p>
  187. * @param command the java executable to find.
  188. * @return the path to the command.
  189. * @since Ant 1.5
  190. */
  191. public static String getJreExecutable(String command) {
  192. if (IS_NETWARE) {
  193. // Extrapolating from:
  194. // "NetWare may have a "java" in that directory, but 99% of
  195. // the time, you don't want to execute it" -- Jeff Tulley
  196. // <JTULLEY@novell.com>
  197. return command;
  198. }
  199. File jExecutable = null;
  200. if (IS_AIX) {
  201. // On IBM's JDK 1.2 the directory layout is different, 1.3 follows
  202. // Sun's layout.
  203. jExecutable = findInDir(JAVA_HOME + "/sh", command);
  204. }
  205. if (jExecutable == null) {
  206. jExecutable = findInDir(JAVA_HOME + "/bin", command);
  207. }
  208. if (jExecutable != null) {
  209. return jExecutable.getAbsolutePath();
  210. } else {
  211. // Unfortunately on Windows java.home doesn't always refer
  212. // to the correct location, so we need to fall back to
  213. // assuming java is somewhere on the PATH.
  214. return addExtension(command);
  215. }
  216. }
  217. /**
  218. * Finds an executable that is part of a JDK installation based on
  219. * the java.home system property.
  220. *
  221. * <p>You typically find them in <code>JAVA_HOME/bin</code> if
  222. * <code>JAVA_HOME</code> points to your JDK installation.</p>
  223. * @param command the java executable to find.
  224. * @return the path to the command.
  225. * @since Ant 1.5
  226. */
  227. public static String getJdkExecutable(String command) {
  228. if (IS_NETWARE) {
  229. // Extrapolating from:
  230. // "NetWare may have a "java" in that directory, but 99% of
  231. // the time, you don't want to execute it" -- Jeff Tulley
  232. // <JTULLEY@novell.com>
  233. return command;
  234. }
  235. File jExecutable = null;
  236. if (IS_AIX) {
  237. // On IBM's JDK 1.2 the directory layout is different, 1.3 follows
  238. // Sun's layout.
  239. jExecutable = findInDir(JAVA_HOME + "/../sh", command);
  240. }
  241. if (jExecutable == null) {
  242. jExecutable = findInDir(JAVA_HOME + "/../bin", command);
  243. }
  244. if (jExecutable != null) {
  245. return jExecutable.getAbsolutePath();
  246. } else {
  247. // fall back to JRE bin directory, also catches JDK 1.0 and 1.1
  248. // where java.home points to the root of the JDK and Mac OS X where
  249. // the whole directory layout is different from Sun's
  250. return getJreExecutable(command);
  251. }
  252. }
  253. /**
  254. * Adds a system specific extension to the name of an executable.
  255. *
  256. * @since Ant 1.5
  257. */
  258. private static String addExtension(String command) {
  259. // This is the most common extension case - exe for windows and OS/2,
  260. // nothing for *nix.
  261. return command + (IS_DOS ? ".exe" : "");
  262. }
  263. /**
  264. * Look for an executable in a given directory.
  265. *
  266. * @return null if the executable cannot be found.
  267. */
  268. private static File findInDir(String dirName, String commandName) {
  269. File dir = FILE_UTILS.normalize(dirName);
  270. File executable = null;
  271. if (dir.exists()) {
  272. executable = new File(dir, addExtension(commandName));
  273. if (!executable.exists()) {
  274. executable = null;
  275. }
  276. }
  277. return executable;
  278. }
  279. /**
  280. * demand creation of the package list.
  281. * When you add a new package, add a new test below.
  282. */
  283. private static void buildJrePackages() {
  284. jrePackages = new Vector();
  285. switch(javaVersionNumber) {
  286. case VERSION_1_6:
  287. case VERSION_1_5:
  288. //In Java1.5, the apache stuff moved.
  289. jrePackages.addElement("com.sun.org.apache");
  290. //fall through.
  291. case VERSION_1_4:
  292. if (javaVersionNumber == VERSION_1_4) {
  293. jrePackages.addElement("org.apache.crimson");
  294. jrePackages.addElement("org.apache.xalan");
  295. jrePackages.addElement("org.apache.xml");
  296. jrePackages.addElement("org.apache.xpath");
  297. }
  298. jrePackages.addElement("org.ietf.jgss");
  299. jrePackages.addElement("org.w3c.dom");
  300. jrePackages.addElement("org.xml.sax");
  301. // fall through
  302. case VERSION_1_3:
  303. jrePackages.addElement("org.omg");
  304. jrePackages.addElement("com.sun.corba");
  305. jrePackages.addElement("com.sun.jndi");
  306. jrePackages.addElement("com.sun.media");
  307. jrePackages.addElement("com.sun.naming");
  308. jrePackages.addElement("com.sun.org.omg");
  309. jrePackages.addElement("com.sun.rmi");
  310. jrePackages.addElement("sunw.io");
  311. jrePackages.addElement("sunw.util");
  312. // fall through
  313. case VERSION_1_2:
  314. jrePackages.addElement("com.sun.java");
  315. jrePackages.addElement("com.sun.image");
  316. // are there any here that we forgot?
  317. // fall through
  318. case VERSION_1_1:
  319. default:
  320. //things like sun.reflection, sun.misc, sun.net
  321. jrePackages.addElement("sun");
  322. jrePackages.addElement("java");
  323. jrePackages.addElement("javax");
  324. break;
  325. }
  326. }
  327. /**
  328. * Testing helper method; kept here for unification of changes.
  329. * @return a list of test classes depending on the java version.
  330. */
  331. public static Vector getJrePackageTestCases() {
  332. Vector tests = new Vector();
  333. tests.addElement("java.lang.Object");
  334. switch(javaVersionNumber) {
  335. case VERSION_1_6:
  336. case VERSION_1_5:
  337. tests.addElement(
  338. "com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl ");
  339. // Fall tru
  340. case VERSION_1_4:
  341. tests.addElement("sun.audio.AudioPlayer");
  342. if (javaVersionNumber == VERSION_1_4) {
  343. tests.addElement("org.apache.crimson.parser.ContentModel");
  344. tests.addElement("org.apache.xalan.processor.ProcessorImport");
  345. tests.addElement("org.apache.xml.utils.URI");
  346. tests.addElement("org.apache.xpath.XPathFactory");
  347. }
  348. tests.addElement("org.ietf.jgss.Oid");
  349. tests.addElement("org.w3c.dom.Attr");
  350. tests.addElement("org.xml.sax.XMLReader");
  351. // fall through
  352. case VERSION_1_3:
  353. tests.addElement("org.omg.CORBA.Any");
  354. tests.addElement("com.sun.corba.se.internal.corba.AnyImpl");
  355. tests.addElement("com.sun.jndi.ldap.LdapURL");
  356. tests.addElement("com.sun.media.sound.Printer");
  357. tests.addElement("com.sun.naming.internal.VersionHelper");
  358. tests.addElement("com.sun.org.omg.CORBA.Initializer");
  359. tests.addElement("sunw.io.Serializable");
  360. tests.addElement("sunw.util.EventListener");
  361. // fall through
  362. case VERSION_1_2:
  363. tests.addElement("javax.accessibility.Accessible");
  364. tests.addElement("sun.misc.BASE64Encoder");
  365. tests.addElement("com.sun.image.codec.jpeg.JPEGCodec");
  366. // fall through
  367. case VERSION_1_1:
  368. default:
  369. //things like sun.reflection, sun.misc, sun.net
  370. tests.addElement("sun.reflect.SerializationConstructorAccessorImpl");
  371. tests.addElement("sun.net.www.http.HttpClient");
  372. tests.addElement("sun.audio.AudioPlayer");
  373. break;
  374. }
  375. return tests;
  376. }
  377. /**
  378. * get a vector of strings of packages built into
  379. * that platforms runtime jar(s)
  380. * @return list of packages.
  381. */
  382. public static Vector getJrePackages() {
  383. if (jrePackages == null) {
  384. buildJrePackages();
  385. }
  386. return jrePackages;
  387. }
  388. /**
  389. *
  390. * Writes the command into a temporary DCL script and returns the
  391. * corresponding File object.
  392. * It is the job of the caller to delete the file on exit.
  393. * @param cmd the command.
  394. * @return the file containing the command.
  395. * @throws IOException if there is an error writing to the file.
  396. */
  397. public static File createVmsJavaOptionFile(String[] cmd)
  398. throws IOException {
  399. File script = FILE_UTILS.createTempFile("ANT", ".JAVA_OPTS", null, false, true);
  400. BufferedWriter out = null;
  401. try {
  402. out = new BufferedWriter(new FileWriter(script));
  403. for (int i = 0; i < cmd.length; i++) {
  404. out.write(cmd[i]);
  405. out.newLine();
  406. }
  407. } finally {
  408. FileUtils.close(out);
  409. }
  410. return script;
  411. }
  412. /**
  413. * Return the value of ${java.home}
  414. * @return the java home value.
  415. */
  416. public static String getJavaHome() {
  417. return JAVA_HOME;
  418. }
  419. }