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.

Diagnostics.java 22 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. /*
  2. * Copyright 2002-2006 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;
  18. import org.apache.tools.ant.util.LoaderUtils;
  19. import org.apache.tools.ant.util.FileUtils;
  20. import org.apache.tools.ant.util.JAXPUtils;
  21. import org.apache.tools.ant.util.ProxySetup;
  22. import org.apache.tools.ant.util.JavaEnvUtils;
  23. import org.apache.tools.ant.launch.Launcher;
  24. import org.xml.sax.XMLReader;
  25. import javax.xml.parsers.SAXParserFactory;
  26. import javax.xml.parsers.SAXParser;
  27. import java.io.File;
  28. import java.io.FilenameFilter;
  29. import java.io.PrintStream;
  30. import java.io.InputStream;
  31. import java.io.IOException;
  32. import java.io.FileOutputStream;
  33. import java.util.Enumeration;
  34. import java.util.Properties;
  35. import java.util.Calendar;
  36. import java.util.TimeZone;
  37. import java.lang.reflect.Method;
  38. import java.lang.reflect.InvocationTargetException;
  39. /**
  40. * A little diagnostic helper that output some information that may help
  41. * in support. It should quickly give correct information about the
  42. * jar existing in ant.home/lib and the jar versions...
  43. *
  44. * @since Ant 1.5
  45. */
  46. public final class Diagnostics {
  47. private static final int BIG_DRIFT_LIMIT = 10000;
  48. private static final int TEST_FILE_SIZE = 32;
  49. private static final int KILOBYTE = 1024;
  50. private static final int SECONDS_PER_MILLISECOND = 1000;
  51. private static final int SECONDS_PER_MINUTE = 60;
  52. private static final int MINUTES_PER_HOUR = 60;
  53. private static final String TEST_CLASS
  54. = "org.apache.tools.ant.taskdefs.optional.Test";
  55. /** utility class */
  56. private Diagnostics() {
  57. // hidden constructor
  58. }
  59. /**
  60. * Check if optional tasks are available. Not that it does not check
  61. * for implementation version. Use <tt>validateVersion()</tt> for this.
  62. * @return <tt>true</tt> if optional tasks are available.
  63. */
  64. public static boolean isOptionalAvailable() {
  65. try {
  66. Class.forName(TEST_CLASS);
  67. } catch (ClassNotFoundException e) {
  68. return false;
  69. }
  70. return true;
  71. }
  72. /**
  73. * Check if core and optional implementation version do match.
  74. * @throws BuildException if the implementation version of optional tasks
  75. * does not match the core implementation version.
  76. */
  77. public static void validateVersion() throws BuildException {
  78. try {
  79. Class optional
  80. = Class.forName(TEST_CLASS);
  81. String coreVersion = getImplementationVersion(Main.class);
  82. String optionalVersion = getImplementationVersion(optional);
  83. if (coreVersion != null && !coreVersion.equals(optionalVersion)) {
  84. throw new BuildException("Invalid implementation version "
  85. + "between Ant core and Ant optional tasks.\n"
  86. + " core : " + coreVersion + "\n"
  87. + " optional: " + optionalVersion);
  88. }
  89. } catch (ClassNotFoundException e) {
  90. // ignore
  91. ignoreThrowable(e);
  92. }
  93. }
  94. /**
  95. * return the list of jar files existing in ANT_HOME/lib
  96. * and that must have been picked up by Ant script.
  97. * @return the list of jar files existing in ant.home/lib or
  98. * <tt>null</tt> if an error occurs.
  99. */
  100. public static File[] listLibraries() {
  101. String home = System.getProperty(MagicNames.ANT_HOME);
  102. if (home == null) {
  103. return null;
  104. }
  105. File libDir = new File(home, "lib");
  106. return listJarFiles(libDir);
  107. }
  108. /**
  109. * get a list of all JAR files in a directory
  110. * @param libDir directory
  111. * @return array of files (or null for no such directory)
  112. */
  113. private static File[] listJarFiles(File libDir) {
  114. FilenameFilter filter = new FilenameFilter() {
  115. public boolean accept(File dir, String name) {
  116. return name.endsWith(".jar");
  117. }
  118. };
  119. File[] files = libDir.listFiles(filter);
  120. return files;
  121. }
  122. /**
  123. * main entry point for command line
  124. * @param args command line arguments.
  125. */
  126. public static void main(String[] args) {
  127. doReport(System.out);
  128. }
  129. /**
  130. * Helper method to get the implementation version.
  131. * @param clazz the class to get the information from.
  132. * @return null if there is no package or implementation version.
  133. * '?.?' for JDK 1.0 or 1.1.
  134. */
  135. private static String getImplementationVersion(Class clazz) {
  136. Package pkg = clazz.getPackage();
  137. return pkg.getImplementationVersion();
  138. }
  139. /**
  140. * what parser are we using.
  141. * @return the classname of the parser
  142. */
  143. private static String getXmlParserName() {
  144. SAXParser saxParser = getSAXParser();
  145. if (saxParser == null) {
  146. return "Could not create an XML Parser";
  147. }
  148. // check to what is in the classname
  149. String saxParserName = saxParser.getClass().getName();
  150. return saxParserName;
  151. }
  152. /**
  153. * Create a JAXP SAXParser
  154. * @return parser or null for trouble
  155. */
  156. private static SAXParser getSAXParser() {
  157. SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
  158. if (saxParserFactory == null) {
  159. return null;
  160. }
  161. SAXParser saxParser = null;
  162. try {
  163. saxParser = saxParserFactory.newSAXParser();
  164. } catch (Exception e) {
  165. // ignore
  166. ignoreThrowable(e);
  167. }
  168. return saxParser;
  169. }
  170. /**
  171. * get the location of the parser
  172. * @return path or null for trouble in tracking it down
  173. */
  174. private static String getXMLParserLocation() {
  175. SAXParser saxParser = getSAXParser();
  176. if (saxParser == null) {
  177. return null;
  178. }
  179. String location = getClassLocation(saxParser.getClass());
  180. return location;
  181. }
  182. private static String getNamespaceParserName() {
  183. try {
  184. XMLReader reader = JAXPUtils.getNamespaceXMLReader();
  185. return reader.getClass().getName();
  186. } catch (BuildException e) {
  187. //ignore
  188. ignoreThrowable(e);
  189. return null;
  190. }
  191. }
  192. private static String getNamespaceParserLocation() {
  193. try {
  194. XMLReader reader = JAXPUtils.getNamespaceXMLReader();
  195. return getClassLocation(reader.getClass());
  196. } catch (BuildException e) {
  197. //ignore
  198. ignoreThrowable(e);
  199. return null;
  200. }
  201. }
  202. /**
  203. * ignore exceptions. This is to allow future
  204. * implementations to log at a verbose level
  205. * @param thrown
  206. */
  207. private static void ignoreThrowable(Throwable thrown) {
  208. }
  209. /**
  210. * get the location of a class. Stolen from axis/webapps/happyaxis.jsp
  211. * @param clazz
  212. * @return the jar file or path where a class was found, or null
  213. */
  214. private static String getClassLocation(Class clazz) {
  215. File f = LoaderUtils.getClassSource(clazz);
  216. return f == null ? null : f.getAbsolutePath();
  217. }
  218. /**
  219. * Print a report to the given stream.
  220. * @param out the stream to print the report to.
  221. */
  222. public static void doReport(PrintStream out) {
  223. out.println("------- Ant diagnostics report -------");
  224. out.println(Main.getAntVersion());
  225. header(out, "Implementation Version");
  226. out.println("core tasks : " + getImplementationVersion(Main.class));
  227. Class optional = null;
  228. try {
  229. optional = Class.forName(TEST_CLASS);
  230. out.println("optional tasks : "
  231. + getImplementationVersion(optional));
  232. } catch (ClassNotFoundException e) {
  233. ignoreThrowable(e);
  234. out.println("optional tasks : not available");
  235. }
  236. header(out, "ANT PROPERTIES");
  237. doReportAntProperties(out);
  238. header(out, "ANT_HOME/lib jar listing");
  239. doReportAntHomeLibraries(out);
  240. header(out, "USER_HOME/.ant/lib jar listing");
  241. doReportUserHomeLibraries(out);
  242. header(out, "Tasks availability");
  243. doReportTasksAvailability(out);
  244. header(out, "org.apache.env.Which diagnostics");
  245. doReportWhich(out);
  246. header(out, "XML Parser information");
  247. doReportParserInfo(out);
  248. header(out, "System properties");
  249. doReportSystemProperties(out);
  250. header(out, "Temp dir");
  251. doReportTempDir(out);
  252. header(out, "Locale information");
  253. doReportLocale(out);
  254. header(out, "Proxy information");
  255. doReportProxy(out);
  256. out.println();
  257. }
  258. private static void header(PrintStream out, String section) {
  259. out.println();
  260. out.println("-------------------------------------------");
  261. out.print(" ");
  262. out.println(section);
  263. out.println("-------------------------------------------");
  264. }
  265. /**
  266. * Report a listing of system properties existing in the current vm.
  267. * @param out the stream to print the properties to.
  268. */
  269. private static void doReportSystemProperties(PrintStream out) {
  270. Properties sysprops = null;
  271. try {
  272. sysprops = System.getProperties();
  273. } catch (SecurityException e) {
  274. ignoreThrowable(e);
  275. out.println("Access to System.getProperties() blocked "
  276. + "by a security manager");
  277. }
  278. for (Enumeration keys = sysprops.propertyNames();
  279. keys.hasMoreElements();) {
  280. String key = (String) keys.nextElement();
  281. String value;
  282. try {
  283. value = System.getProperty(key);
  284. } catch (SecurityException e) {
  285. value = "Access to this property blocked by a security manager";
  286. }
  287. out.println(key + " : " + value);
  288. }
  289. }
  290. /**
  291. * Report the content of ANT_HOME/lib directory
  292. * @param out the stream to print the content to
  293. */
  294. private static void doReportAntProperties(PrintStream out) {
  295. Project p = new Project();
  296. p.initProperties();
  297. out.println(MagicNames.ANT_VERSION + ": " + p.getProperty(MagicNames.ANT_VERSION));
  298. out.println(MagicNames.ANT_JAVA_VERSION + ": " + p.getProperty(MagicNames.ANT_JAVA_VERSION));
  299. out.println(MagicNames.ANT_LIB + ": " + p.getProperty(MagicNames.ANT_LIB));
  300. out.println(MagicNames.ANT_HOME + ": " + p.getProperty(MagicNames.ANT_HOME));
  301. }
  302. /**
  303. * Report the content of ANT_HOME/lib directory
  304. * @param out the stream to print the content to
  305. */
  306. private static void doReportAntHomeLibraries(PrintStream out) {
  307. out.println(MagicNames.ANT_HOME + ": " + System.getProperty(MagicNames.ANT_HOME));
  308. File[] libs = listLibraries();
  309. printLibraries(libs, out);
  310. }
  311. /**
  312. * Report the content of ~/.ant/lib directory
  313. *
  314. * @param out the stream to print the content to
  315. */
  316. private static void doReportUserHomeLibraries(PrintStream out) {
  317. String home = System.getProperty(Launcher.USER_HOMEDIR);
  318. out.println("user.home: " + home);
  319. File libDir = new File(home, Launcher.USER_LIBDIR);
  320. File[] libs = listJarFiles(libDir);
  321. printLibraries(libs, out);
  322. }
  323. /**
  324. * list the libraries
  325. * @param libs array of libraries (can be null)
  326. * @param out output stream
  327. */
  328. private static void printLibraries(File[] libs, PrintStream out) {
  329. if (libs == null) {
  330. out.println("No such directory.");
  331. return;
  332. }
  333. for (int i = 0; i < libs.length; i++) {
  334. out.println(libs[i].getName()
  335. + " (" + libs[i].length() + " bytes)");
  336. }
  337. }
  338. /**
  339. * Call org.apache.env.Which if available
  340. * @param out the stream to print the content to.
  341. */
  342. private static void doReportWhich(PrintStream out) {
  343. Throwable error = null;
  344. try {
  345. Class which = Class.forName("org.apache.env.Which");
  346. Method method
  347. = which.getMethod("main", new Class[]{String[].class});
  348. method.invoke(null, new Object[]{new String[]{}});
  349. } catch (ClassNotFoundException e) {
  350. out.println("Not available.");
  351. out.println("Download it at http://xml.apache.org/commons/");
  352. } catch (InvocationTargetException e) {
  353. error = e.getTargetException() == null ? e : e.getTargetException();
  354. } catch (Throwable e) {
  355. error = e;
  356. }
  357. // report error if something weird happens...this is diagnostic.
  358. if (error != null) {
  359. out.println("Error while running org.apache.env.Which");
  360. error.printStackTrace();
  361. }
  362. }
  363. /**
  364. * Create a report about non-available tasks that are defined in the
  365. * mapping but could not be found via lookup. It might generally happen
  366. * because Ant requires multiple libraries to compile and one of them
  367. * was missing when compiling Ant.
  368. * @param out the stream to print the tasks report to
  369. * <tt>null</tt> for a missing stream (ie mapping).
  370. */
  371. private static void doReportTasksAvailability(PrintStream out) {
  372. InputStream is = Main.class.getResourceAsStream(
  373. MagicNames.TASKDEF_PROPERTIES_RESOURCE);
  374. if (is == null) {
  375. out.println("None available");
  376. } else {
  377. Properties props = new Properties();
  378. try {
  379. props.load(is);
  380. for (Enumeration keys = props.keys(); keys.hasMoreElements();) {
  381. String key = (String) keys.nextElement();
  382. String classname = props.getProperty(key);
  383. try {
  384. Class.forName(classname);
  385. props.remove(key);
  386. } catch (ClassNotFoundException e) {
  387. out.println(key + " : Not Available "
  388. + "(the implementation class is not present)");
  389. } catch (NoClassDefFoundError e) {
  390. String pkg = e.getMessage().replace('/', '.');
  391. out.println(key + " : Missing dependency " + pkg);
  392. } catch (LinkageError e) {
  393. out.println(key + " : Initialization error");
  394. }
  395. }
  396. if (props.size() == 0) {
  397. out.println("All defined tasks are available");
  398. } else {
  399. out.println("A task being missing/unavailable should only "
  400. +"matter if you are trying to use it");
  401. }
  402. } catch (IOException e) {
  403. out.println(e.getMessage());
  404. }
  405. }
  406. }
  407. /**
  408. * tell the user about the XML parser
  409. * @param out
  410. */
  411. private static void doReportParserInfo(PrintStream out) {
  412. String parserName = getXmlParserName();
  413. String parserLocation = getXMLParserLocation();
  414. printParserInfo(out, "XML Parser", parserName, parserLocation);
  415. printParserInfo(out, "Namespace-aware parser",
  416. getNamespaceParserName(),
  417. getNamespaceParserLocation());
  418. }
  419. private static void printParserInfo(PrintStream out,
  420. String parserType,
  421. String parserName,
  422. String parserLocation) {
  423. if (parserName == null) {
  424. parserName = "unknown";
  425. }
  426. if (parserLocation == null) {
  427. parserLocation = "unknown";
  428. }
  429. out.println(parserType +" : " + parserName);
  430. out.println(parserType +" Location: " + parserLocation);
  431. }
  432. /**
  433. * try and create a temp file in our temp dir; this
  434. * checks that it has space and access.
  435. * We also do some clock reporting.
  436. * @param out
  437. */
  438. private static void doReportTempDir(PrintStream out) {
  439. String tempdir = System.getProperty("java.io.tmpdir");
  440. if (tempdir == null) {
  441. out.println("Warning: java.io.tmpdir is undefined");
  442. return;
  443. }
  444. out.println("Temp dir is " + tempdir);
  445. File tempDirectory = new File(tempdir);
  446. if (!tempDirectory.exists()) {
  447. out.println("Warning, java.io.tmpdir directory does not exist: "
  448. + tempdir);
  449. return;
  450. }
  451. //create the file
  452. long now = System.currentTimeMillis();
  453. File tempFile = null;
  454. FileOutputStream fileout = null;
  455. try {
  456. tempFile = File.createTempFile("diag", "txt", tempDirectory);
  457. //do some writing to it
  458. fileout = new FileOutputStream(tempFile);
  459. byte[] buffer = new byte[KILOBYTE];
  460. for (int i = 0; i < TEST_FILE_SIZE; i++) {
  461. fileout.write(buffer);
  462. }
  463. fileout.close();
  464. fileout = null;
  465. long filetime = tempFile.lastModified();
  466. tempFile.delete();
  467. out.println("Temp dir is writeable");
  468. long drift = filetime - now;
  469. out.println("Temp dir alignment with system clock is " + drift + " ms");
  470. if (Math.abs(drift) > BIG_DRIFT_LIMIT) {
  471. out.println("Warning: big clock drift -maybe a network filesystem");
  472. }
  473. } catch (IOException e) {
  474. ignoreThrowable(e);
  475. out.println("Failed to create a temporary file in the temp dir "
  476. + tempdir);
  477. out.println("File " + tempFile + " could not be created/written to");
  478. } finally {
  479. FileUtils.close(fileout);
  480. if (tempFile != null && tempFile.exists()) {
  481. tempFile.delete();
  482. }
  483. }
  484. }
  485. /**
  486. * Report locale information
  487. * @param out stream to print to
  488. */
  489. private static void doReportLocale(PrintStream out) {
  490. //calendar stuff.
  491. Calendar cal = Calendar.getInstance();
  492. TimeZone tz = cal.getTimeZone();
  493. out.println("Timezone " + tz.getDisplayName()
  494. + " offset=" + tz.getOffset(cal.get(Calendar.ERA),
  495. cal.get(Calendar.YEAR),
  496. cal.get(Calendar.MONTH),
  497. cal.get(Calendar.DAY_OF_MONTH),
  498. cal.get(Calendar.DAY_OF_WEEK),
  499. ((cal.get(Calendar.HOUR_OF_DAY) * MINUTES_PER_HOUR
  500. + cal.get(Calendar.MINUTE)) * SECONDS_PER_MINUTE
  501. + cal.get(Calendar.SECOND)) * SECONDS_PER_MILLISECOND
  502. + cal.get(Calendar.MILLISECOND)));
  503. }
  504. /**
  505. * print a property name="value" pair, or name=[undefined] if there is none
  506. * @param out
  507. * @param name
  508. */
  509. private static void printProperty(PrintStream out,String name) {
  510. out.print(name);
  511. out.print(" = ");
  512. String value=System.getProperty(name);
  513. if(value!=null) {
  514. out.print('"');
  515. out.print(value);
  516. out.println('"');
  517. } else {
  518. out.println("[undefined]");
  519. }
  520. }
  521. /**
  522. * Report proxy information
  523. *
  524. * @param out stream to print to
  525. */
  526. private static void doReportProxy(PrintStream out) {
  527. if(JavaEnvUtils.getJavaVersionNumber()>=15) {
  528. printProperty(out, ProxySetup.USE_SYSTEM_PROXIES);
  529. }
  530. printProperty(out,ProxySetup.HTTP_PROXY_HOST);
  531. printProperty(out, ProxySetup.HTTP_PROXY_PORT);
  532. printProperty(out, ProxySetup.HTTP_PROXY_USERNAME);
  533. printProperty(out, ProxySetup.HTTP_PROXY_PASSWORD);
  534. printProperty(out, ProxySetup.HTTP_NON_PROXY_HOSTS);
  535. printProperty(out, ProxySetup.HTTPS_PROXY_HOST);
  536. printProperty(out, ProxySetup.HTTPS_PROXY_PORT);
  537. printProperty(out, ProxySetup.HTTPS_NON_PROXY_HOSTS);
  538. printProperty(out, ProxySetup.FTP_PROXY_HOST);
  539. printProperty(out, ProxySetup.FTP_PROXY_PORT);
  540. printProperty(out, ProxySetup.FTP_NON_PROXY_HOSTS);
  541. printProperty(out, ProxySetup.SOCKS_PROXY_HOST);
  542. printProperty(out, ProxySetup.SOCKS_PROXY_PORT);
  543. printProperty(out, ProxySetup.SOCKS_PROXY_USERNAME);
  544. printProperty(out, ProxySetup.SOCKS_PROXY_PASSWORD);
  545. final String proxyDiagClassname="org.apache.tools.ant.util.java15.ProxyDiagnostics";
  546. try {
  547. Class proxyDiagClass = Class.forName(proxyDiagClassname);
  548. Object instance =proxyDiagClass.newInstance();
  549. out.println("Java1.5+ proxy settings");
  550. out.println(instance.toString());
  551. } catch (ClassNotFoundException e) {
  552. //not included, do nothing
  553. } catch (IllegalAccessException e) {
  554. //not included, do nothing
  555. } catch (InstantiationException e) {
  556. //not included, do nothing
  557. }
  558. }
  559. }