001 /* 002 * Copyright 2002-2004 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 */ 017 package org.apache.tools.ant; 018 019 import org.apache.tools.ant.util.LoaderUtils; 020 021 import javax.xml.parsers.SAXParserFactory; 022 import javax.xml.parsers.SAXParser; 023 import java.io.File; 024 import java.io.FilenameFilter; 025 import java.io.PrintStream; 026 import java.io.InputStream; 027 import java.io.IOException; 028 import java.util.Enumeration; 029 import java.util.Properties; 030 import java.lang.reflect.Method; 031 import java.lang.reflect.InvocationTargetException; 032 033 /** 034 * A little diagnostic helper that output some information that may help 035 * in support. It should quickly give correct information about the 036 * jar existing in ant.home/lib and the jar versions... 037 * 038 * @since Ant 1.5 039 */ 040 public final class Diagnostics { 041 042 private static final String TEST_CLASS 043 = "org.apache.tools.ant.taskdefs.optional.Test"; 044 045 /** utility class */ 046 private Diagnostics() { 047 } 048 049 /** 050 * Check if optional tasks are available. Not that it does not check 051 * for implementation version. Use <tt>validateVersion()</tt> for this. 052 * @return <tt>true</tt> if optional tasks are available. 053 */ 054 public static boolean isOptionalAvailable() { 055 try { 056 Class.forName(TEST_CLASS); 057 } catch (ClassNotFoundException e) { 058 return false; 059 } 060 return true; 061 } 062 063 /** 064 * Check if core and optional implementation version do match. 065 * @throws BuildException if the implementation version of optional tasks 066 * does not match the core implementation version. 067 */ 068 public static void validateVersion() throws BuildException { 069 try { 070 Class optional 071 = Class.forName("org.apache.tools.ant.taskdefs.optional.Test"); 072 String coreVersion = getImplementationVersion(Main.class); 073 String optionalVersion = getImplementationVersion(optional); 074 075 if (coreVersion != null && !coreVersion.equals(optionalVersion)) { 076 throw new BuildException("Invalid implementation version " 077 + "between Ant core and Ant optional tasks.\n" 078 + " core : " + coreVersion + "\n" 079 + " optional: " + optionalVersion); 080 } 081 } catch (ClassNotFoundException e) { 082 // ignore 083 } 084 } 085 086 /** 087 * return the list of jar files existing in ANT_HOME/lib 088 * and that must have been picked up by Ant script. 089 * @return the list of jar files existing in ant.home/lib or 090 * <tt>null</tt> if an error occurs. 091 */ 092 public static File[] listLibraries() { 093 String home = System.getProperty("ant.home"); 094 if (home == null) { 095 return null; 096 } 097 File libDir = new File(home, "lib"); 098 FilenameFilter filter = new FilenameFilter() { 099 public boolean accept(File dir, String name) { 100 return name.endsWith(".jar"); 101 } 102 }; 103 // listFiles is JDK 1.2+ method... 104 String[] filenames = libDir.list(filter); 105 if (filenames == null) { 106 return null; 107 } 108 File[] files = new File[filenames.length]; 109 for (int i = 0; i < filenames.length; i++) { 110 files[i] = new File(libDir, filenames[i]); 111 } 112 return files; 113 } 114 115 /** 116 * main entry point for command line 117 * @param args command line arguments. 118 */ 119 public static void main(String[] args) { 120 doReport(System.out); 121 } 122 123 124 /** 125 * Helper method to get the implementation version. 126 * @param clazz the class to get the information from. 127 * @return null if there is no package or implementation version. 128 * '?.?' for JDK 1.0 or 1.1. 129 */ 130 private static String getImplementationVersion(Class clazz) { 131 try { 132 // Package pkg = clazz.getPackage(); 133 Method method = Class.class.getMethod("getPackage", new Class[0]); 134 Object pkg = method.invoke(clazz, null); 135 if (pkg != null) { 136 // pkg.getImplementationVersion(); 137 method = pkg.getClass().getMethod("getImplementationVersion", new Class[0]); 138 Object version = method.invoke(pkg, null); 139 return (String) version; 140 } 141 } catch (Exception e) { 142 // JDK < 1.2 should land here because the methods above don't exist. 143 return "?.?"; 144 } 145 return null; 146 } 147 148 /** 149 * what parser are we using. 150 * @return the classname of the parser 151 */ 152 private static String getXmlParserName() { 153 SAXParser saxParser = getSAXParser(); 154 if (saxParser == null) { 155 return "Could not create an XML Parser"; 156 } 157 158 // check to what is in the classname 159 String saxParserName = saxParser.getClass().getName(); 160 return saxParserName; 161 } 162 163 /** 164 * Create a JAXP SAXParser 165 * @return parser or null for trouble 166 */ 167 private static SAXParser getSAXParser() { 168 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); 169 if (saxParserFactory == null) { 170 return null; 171 } 172 SAXParser saxParser = null; 173 try { 174 saxParser = saxParserFactory.newSAXParser(); 175 } catch (Exception e) { 176 // ignore 177 } 178 return saxParser; 179 } 180 181 /** 182 * get the location of the parser 183 * @return path or null for trouble in tracking it down 184 */ 185 186 private static String getXMLParserLocation() { 187 SAXParser saxParser = getSAXParser(); 188 if (saxParser == null) { 189 return null; 190 } 191 String location = getClassLocation(saxParser.getClass()); 192 return location; 193 } 194 195 /** 196 * get the location of a class. Stolen from axis/webapps/happyaxis.jsp 197 * @param clazz 198 * @return the jar file or path where a class was found, or null 199 */ 200 201 private static String getClassLocation(Class clazz) { 202 File f = LoaderUtils.getClassSource(clazz); 203 return f == null ? null : f.getAbsolutePath(); 204 } 205 206 207 /** 208 * Print a report to the given stream. 209 * @param out the stream to print the report to. 210 */ 211 public static void doReport(PrintStream out) { 212 out.println("------- Ant diagnostics report -------"); 213 out.println(Main.getAntVersion()); 214 out.println(); 215 out.println("-------------------------------------------"); 216 out.println(" Implementation Version (JDK1.2+ only)"); 217 out.println("-------------------------------------------"); 218 out.println("core tasks : " + getImplementationVersion(Main.class)); 219 220 Class optional = null; 221 try { 222 optional = Class.forName( 223 "org.apache.tools.ant.taskdefs.optional.Test"); 224 out.println("optional tasks : " 225 + getImplementationVersion(optional)); 226 } catch (ClassNotFoundException e) { 227 out.println("optional tasks : not available"); 228 } 229 230 out.println(); 231 out.println("-------------------------------------------"); 232 out.println(" ANT_HOME/lib jar listing"); 233 out.println("-------------------------------------------"); 234 doReportLibraries(out); 235 236 out.println(); 237 out.println("-------------------------------------------"); 238 out.println(" Tasks availability"); 239 out.println("-------------------------------------------"); 240 doReportTasksAvailability(out); 241 242 out.println(); 243 out.println("-------------------------------------------"); 244 out.println(" org.apache.env.Which diagnostics"); 245 out.println("-------------------------------------------"); 246 doReportWhich(out); 247 248 249 out.println(); 250 out.println("-------------------------------------------"); 251 out.println(" XML Parser information"); 252 out.println("-------------------------------------------"); 253 doReportParserInfo(out); 254 255 out.println(); 256 out.println("-------------------------------------------"); 257 out.println(" System properties"); 258 out.println("-------------------------------------------"); 259 doReportSystemProperties(out); 260 261 out.println(); 262 } 263 264 /** 265 * Report a listing of system properties existing in the current vm. 266 * @param out the stream to print the properties to. 267 */ 268 private static void doReportSystemProperties(PrintStream out) { 269 for (Enumeration keys = System.getProperties().keys(); 270 keys.hasMoreElements();) { 271 String key = (String) keys.nextElement(); 272 out.println(key + " : " + System.getProperty(key)); 273 } 274 } 275 276 277 /** 278 * Report the content of ANT_HOME/lib directory 279 * @param out the stream to print the content to 280 */ 281 private static void doReportLibraries(PrintStream out) { 282 out.println("ant.home: " + System.getProperty("ant.home")); 283 File[] libs = listLibraries(); 284 if (libs == null) { 285 out.println("Unable to list libraries."); 286 return; 287 } 288 for (int i = 0; i < libs.length; i++) { 289 out.println(libs[i].getName() 290 + " (" + libs[i].length() + " bytes)"); 291 } 292 } 293 294 295 /** 296 * Call org.apache.env.Which if available 297 * @param out the stream to print the content to. 298 */ 299 private static void doReportWhich(PrintStream out) { 300 Throwable error = null; 301 try { 302 Class which = Class.forName("org.apache.env.Which"); 303 Method method 304 = which.getMethod("main", new Class[]{String[].class}); 305 method.invoke(null, new Object[]{new String[]{}}); 306 } catch (ClassNotFoundException e) { 307 out.println("Not available."); 308 out.println("Download it at http://xml.apache.org/commons/"); 309 } catch (InvocationTargetException e) { 310 error = e.getTargetException() == null ? e : e.getTargetException(); 311 } catch (Throwable e) { 312 error = e; 313 } 314 // report error if something weird happens...this is diagnostic. 315 if (error != null) { 316 out.println("Error while running org.apache.env.Which"); 317 error.printStackTrace(); 318 } 319 } 320 321 /** 322 * Create a report about non-available tasks that are defined in the 323 * mapping but could not be found via lookup. It might generally happen 324 * because Ant requires multiple libraries to compile and one of them 325 * was missing when compiling Ant. 326 * @param out the stream to print the tasks report to 327 * <tt>null</tt> for a missing stream (ie mapping). 328 */ 329 private static void doReportTasksAvailability(PrintStream out) { 330 InputStream is = Main.class.getResourceAsStream( 331 "/org/apache/tools/ant/taskdefs/defaults.properties"); 332 if (is == null) { 333 out.println("None available"); 334 } else { 335 Properties props = new Properties(); 336 try { 337 props.load(is); 338 for (Enumeration keys = props.keys(); keys.hasMoreElements();) { 339 String key = (String) keys.nextElement(); 340 String classname = props.getProperty(key); 341 try { 342 Class.forName(classname); 343 props.remove(key); 344 } catch (ClassNotFoundException e) { 345 out.println(key + " : Not Available"); 346 } catch (NoClassDefFoundError e) { 347 String pkg = e.getMessage().replace('/', '.'); 348 out.println(key + " : Missing dependency " + pkg); 349 } catch (Error e) { 350 out.println(key + " : Initialization error"); 351 } 352 } Rate353 if (props.size() == 0) { 354 out.println("All defined tasks are available"); 355 } 356 } catch (IOException e) { 357 out.println(e.getMessage()); 358 } 359 } 360 } 361 362 /** 363 * tell the user about the XML parser 364 * @param out 365 */ 366 private static void doReportParserInfo(PrintStream out) { 367 String parserName = getXmlParserName(); 368 String parserLocation = getXMLParserLocation(); 369 if (parserName == null) { 370 parserName = "unknown"; 371 } 372 if (parserLocation == null) { 373 parserLocation = "unknown"; 374 } 375 out.println("XML Parser : " + parserName); 376 out.println("XML Parser Location: " + parserLocation); 377 } 378 }