1 18 19 package org.apache.tools.ant; 20 21 import java.io.FileOutputStream ; 22 import java.io.IOException ; 23 import java.io.OutputStream ; 24 import java.io.OutputStreamWriter ; 25 import java.io.PrintStream ; 26 import java.io.Writer ; 27 import java.util.Hashtable ; 28 import java.util.Stack ; 29 import java.util.Enumeration ; 30 import javax.xml.parsers.DocumentBuilder ; 31 import javax.xml.parsers.DocumentBuilderFactory ; 32 import org.apache.tools.ant.util.DOMElementWriter; 33 import org.apache.tools.ant.util.StringUtils; 34 import org.w3c.dom.Document ; 35 import org.w3c.dom.Element ; 36 import org.w3c.dom.Text ; 37 38 52 public class XmlLogger implements BuildLogger { 53 54 private int msgOutputLevel = Project.MSG_DEBUG; 55 private PrintStream outStream; 56 57 58 private static DocumentBuilder builder = getDocumentBuilder(); 59 60 66 private static DocumentBuilder getDocumentBuilder() { 67 try { 68 return DocumentBuilderFactory.newInstance().newDocumentBuilder(); 69 } catch (Exception exc) { 70 throw new ExceptionInInitializerError (exc); 71 } 72 } 73 74 75 private static final String BUILD_TAG = "build"; 76 77 private static final String TARGET_TAG = "target"; 78 79 private static final String TASK_TAG = "task"; 80 81 private static final String MESSAGE_TAG = "message"; 82 83 private static final String NAME_ATTR = "name"; 84 85 private static final String TIME_ATTR = "time"; 86 87 private static final String PRIORITY_ATTR = "priority"; 88 89 private static final String LOCATION_ATTR = "location"; 90 91 private static final String ERROR_ATTR = "error"; 92 93 private static final String STACKTRACE_TAG = "stacktrace"; 94 95 96 private Document doc = builder.newDocument(); 97 98 private Hashtable tasks = new Hashtable (); 99 100 private Hashtable targets = new Hashtable (); 101 105 private Hashtable threadStacks = new Hashtable (); 106 109 private TimedElement buildElement = null; 110 111 112 private static class TimedElement { 113 117 private long startTime; 118 119 private Element element; 120 public String toString() { 121 return element.getTagName() + ":" + element.getAttribute("name"); 122 } 123 } 124 125 128 public XmlLogger() { 129 } 130 131 137 public void buildStarted(BuildEvent event) { 138 buildElement = new TimedElement(); 139 buildElement.startTime = System.currentTimeMillis(); 140 buildElement.element = doc.createElement(BUILD_TAG); 141 } 142 143 150 public void buildFinished(BuildEvent event) { 151 long totalTime = System.currentTimeMillis() - buildElement.startTime; 152 buildElement.element.setAttribute(TIME_ATTR, 153 DefaultLogger.formatTime(totalTime)); 154 155 if (event.getException() != null) { 156 buildElement.element.setAttribute(ERROR_ATTR, 157 event.getException().toString()); 158 Throwable t = event.getException(); 161 Text errText = doc.createCDATASection(StringUtils.getStackTrace(t)); 162 Element stacktrace = doc.createElement(STACKTRACE_TAG); 163 stacktrace.appendChild(errText); 164 buildElement.element.appendChild(stacktrace); 165 } 166 167 String outFilename = event.getProject().getProperty("XmlLogger.file"); 168 if (outFilename == null) { 169 outFilename = "log.xml"; 170 } 171 String xslUri 172 = event.getProject().getProperty("ant.XmlLogger.stylesheet.uri"); 173 if (xslUri == null) { 174 xslUri = "log.xsl"; 175 } 176 Writer out = null; 177 try { 178 OutputStream stream = outStream; 181 if (stream == null) { 182 stream = new FileOutputStream (outFilename); 183 } 184 out = new OutputStreamWriter (stream, "UTF8"); 185 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 186 if (xslUri.length() > 0) { 187 out.write("<?xml-stylesheet type=\"text/xsl\" HREF=\"" 188 + xslUri + "\"?>\n\n"); 189 } 190 (new DOMElementWriter()).write(buildElement.element, out, 0, "\t"); 191 out.flush(); 192 } catch (IOException exc) { 193 throw new BuildException("Unable to write log file", exc); 194 } finally { 195 if (out != null) { 196 try { 197 out.close(); 198 } catch (IOException e) { 199 } 201 } 202 } 203 buildElement = null; 204 } 205 206 210 private Stack getStack() { 211 Stack threadStack = (Stack ) threadStacks.get(Thread.currentThread()); 212 if (threadStack == null) { 213 threadStack = new Stack (); 214 threadStacks.put(Thread.currentThread(), threadStack); 215 } 216 220 return threadStack; 221 } 222 223 231 public void targetStarted(BuildEvent event) { 232 Target target = event.getTarget(); 233 TimedElement targetElement = new TimedElement(); 234 targetElement.startTime = System.currentTimeMillis(); 235 targetElement.element = doc.createElement(TARGET_TAG); 236 targetElement.element.setAttribute(NAME_ATTR, target.getName()); 237 targets.put(target, targetElement); 238 getStack().push(targetElement); 239 } 240 241 248 public void targetFinished(BuildEvent event) { 249 Target target = event.getTarget(); 250 TimedElement targetElement = (TimedElement) targets.get(target); 251 if (targetElement != null) { 252 long totalTime 253 = System.currentTimeMillis() - targetElement.startTime; 254 targetElement.element.setAttribute(TIME_ATTR, 255 DefaultLogger.formatTime(totalTime)); 256 257 TimedElement parentElement = null; 258 Stack threadStack = getStack(); 259 if (!threadStack.empty()) { 260 TimedElement poppedStack = (TimedElement) threadStack.pop(); 261 if (poppedStack != targetElement) { 262 throw new RuntimeException ("Mismatch - popped element = " 263 + poppedStack 264 + " finished target element = " 265 + targetElement); 266 } 267 if (!threadStack.empty()) { 268 parentElement = (TimedElement) threadStack.peek(); 269 } 270 } 271 if (parentElement == null) { 272 buildElement.element.appendChild(targetElement.element); 273 } else { 274 parentElement.element.appendChild(targetElement.element); 275 } 276 } 277 targets.remove(target); 278 } 279 280 288 public void taskStarted(BuildEvent event) { 289 TimedElement taskElement = new TimedElement(); 290 taskElement.startTime = System.currentTimeMillis(); 291 taskElement.element = doc.createElement(TASK_TAG); 292 293 Task task = event.getTask(); 294 String name = event.getTask().getTaskName(); 295 if (name == null) { 296 name = ""; 297 } 298 taskElement.element.setAttribute(NAME_ATTR, name); 299 taskElement.element.setAttribute(LOCATION_ATTR, 300 event.getTask().getLocation().toString()); 301 tasks.put(task, taskElement); 302 getStack().push(taskElement); 303 } 304 305 312 public void taskFinished(BuildEvent event) { 313 Task task = event.getTask(); 314 TimedElement taskElement = (TimedElement) tasks.get(task); 315 if (taskElement != null) { 316 long totalTime = System.currentTimeMillis() - taskElement.startTime; 317 taskElement.element.setAttribute(TIME_ATTR, 318 DefaultLogger.formatTime(totalTime)); 319 Target target = task.getOwningTarget(); 320 TimedElement targetElement = null; 321 if (target != null) { 322 targetElement = (TimedElement) targets.get(target); 323 } 324 if (targetElement == null) { 325 buildElement.element.appendChild(taskElement.element); 326 } else { 327 targetElement.element.appendChild(taskElement.element); 328 } 329 Stack threadStack = getStack(); 330 if (!threadStack.empty()) { 331 TimedElement poppedStack = (TimedElement) threadStack.pop(); 332 if (poppedStack != taskElement) { 333 throw new RuntimeException ("Mismatch - popped element = " 334 + poppedStack + " finished task element = " 335 + taskElement); 336 } 337 } 338 tasks.remove(task); 339 } else { 340 throw new RuntimeException ("Unknown task " + task + " not in " + tasks); 341 } 342 } 343 344 345 351 private TimedElement getTaskElement(Task task) { 352 TimedElement element = (TimedElement) tasks.get(task); 353 if (element != null) { 354 return element; 355 } 356 357 for (Enumeration e = tasks.keys(); e.hasMoreElements();) { 358 Task key = (Task) e.nextElement(); 359 if (key instanceof UnknownElement) { 360 if (((UnknownElement) key).getTask() == task) { 361 return (TimedElement) tasks.get(key); 362 } 363 } 364 } 365 366 return null; 367 } 368 369 377 public void messageLogged(BuildEvent event) { 378 int priority = event.getPriority(); 379 if (priority > msgOutputLevel) { 380 return; 381 } 382 Element messageElement = doc.createElement(MESSAGE_TAG); 383 384 String name = "debug"; 385 switch (event.getPriority()) { 386 case Project.MSG_ERR: 387 name = "error"; 388 break; 389 case Project.MSG_WARN: 390 name = "warn"; 391 break; 392 case Project.MSG_INFO: 393 name = "info"; 394 break; 395 default: 396 name = "debug"; 397 break; 398 } 399 messageElement.setAttribute(PRIORITY_ATTR, name); 400 401 Throwable ex = event.getException(); 402 if (Project.MSG_DEBUG <= msgOutputLevel && ex != null) { 403 Text errText = doc.createCDATASection(StringUtils.getStackTrace(ex)); 404 Element stacktrace = doc.createElement(STACKTRACE_TAG); 405 stacktrace.appendChild(errText); 406 buildElement.element.appendChild(stacktrace); 407 } 408 Text messageText = doc.createCDATASection(event.getMessage()); 409 messageElement.appendChild(messageText); 410 411 TimedElement parentElement = null; 412 413 Task task = event.getTask(); 414 415 Target target = event.getTarget(); 416 if (task != null) { 417 parentElement = getTaskElement(task); 418 } 419 if (parentElement == null && target != null) { 420 parentElement = (TimedElement) targets.get(target); 421 } 422 423 434 435 if (parentElement != null) { 436 parentElement.element.appendChild(messageElement); 437 } else { 438 buildElement.element.appendChild(messageElement); 439 } 440 } 441 442 444 451 public void setMessageOutputLevel(int level) { 452 msgOutputLevel = level; 453 } 454 455 461 public void setOutputPrintStream(PrintStream output) { 462 this.outStream = new PrintStream (output, true); 463 } 464 465 471 public void setEmacsMode(boolean emacsMode) { 472 } 473 474 481 public void setErrorPrintStream(PrintStream err) { 482 } 483 484 } 485 | Popular Tags |