diff --git a/src/main/org/apache/tools/ant/XmlLogger.java b/src/main/org/apache/tools/ant/XmlLogger.java index db2d61cb7..ea0ad20d4 100644 --- a/src/main/org/apache/tools/ant/XmlLogger.java +++ b/src/main/org/apache/tools/ant/XmlLogger.java @@ -71,15 +71,22 @@ import org.apache.tools.ant.util.DOMElementWriter; import org.apache.tools.ant.util.StringUtils; /** - * Generates a "log.xml" file in the current directory with - * an XML description of what happened during a build. + * Generates a file in the current directory with + * an XML description of what happened during a build. + * The default filename is "log.xml", but this can be overridden + * with the property XmlLogger.file * - * @see Project#addBuildListener(BuildListener) + * @see Project#addBuildListener(BuildListener) */ public class XmlLogger implements BuildListener { + /** DocumentBuilder to use when creating the document to start with. */ private final static DocumentBuilder builder = getDocumentBuilder(); + /** + * Returns a default DocumentBuilder instance or throws an + * ExceptionInInitializerError if it can't be created. + */ private static DocumentBuilder getDocumentBuilder() { try { return DocumentBuilderFactory.newInstance().newDocumentBuilder(); @@ -89,24 +96,52 @@ public class XmlLogger implements BuildListener { } } - // XML constants for tag names and attribute names + /** XML element name for a build. */ private final static String BUILD_TAG = "build"; + /** XML element name for a target. */ private final static String TARGET_TAG = "target"; + /** XML element name for a task. */ private final static String TASK_TAG = "task"; + /** XML element name for a message. */ private final static String MESSAGE_TAG = "message"; + /** XML attribute name for a name. */ private final static String NAME_ATTR = "name"; + /** XML attribute name for a time. */ private final static String TIME_ATTR = "time"; + /** XML attribute name for a message priority. */ private final static String PRIORITY_ATTR = "priority"; + /** XML attribute name for a file location. */ private final static String LOCATION_ATTR = "location"; + /** XML attribute name for an error description. */ private final static String ERROR_ATTR = "error"; + /** XML element name for a stack trace. */ private final static String STACKTRACE_TAG = "stacktrace"; + /** The complete log document for this build. */ private Document doc = builder.newDocument(); + // XXX: (Jon Skeet) I don't see the use for these maps, myself, + // and they don't seem threadsafe to me. Is there something + // preventing a task being executed by two different threads + // at the same time? If not, we could get a mismatch error + // for no good reason. I'd have thought that checking + // the information in the element stored in the TimedElement + // would give enough of a validity check and end up being more + // threadsafe. + /** Mapping for when tasks started (Task to TimedElement). */ private Hashtable tasks = new Hashtable(); + /** Mapping for when targets started (Task to TimedElement). */ private Hashtable targets = new Hashtable(); + /** + * Mapping of threads to stacks of elements + * (Thread to Stack of TimedElement). + */ private Hashtable threadStacks = new Hashtable(); + /** + * When the build started. + */ private TimedElement buildElement = null; + /** Utility class representing the time an element started. */ private static class TimedElement { long startTime; Element element; @@ -118,12 +153,25 @@ public class XmlLogger implements BuildListener { public XmlLogger() { } + /** + * Fired when the build starts, this builds the top-level element for the + * document and remembers the time of the start of the build. + * + * @param event Ignored. + */ public void buildStarted(BuildEvent event) { buildElement = new TimedElement(); buildElement.startTime = System.currentTimeMillis(); buildElement.element = doc.createElement(BUILD_TAG); } + /** + * Fired when the build finishes, this adds the time taken and any + * error stacktrace to the build element and writes the document to disk. + * + * @param event An event with any relevant extra information. + * Will not be null. + */ public void buildFinished(BuildEvent event) { long totalTime = System.currentTimeMillis() - buildElement.startTime; buildElement.element.setAttribute(TIME_ATTR, DefaultLogger.formatTime(totalTime)); @@ -165,6 +213,10 @@ public class XmlLogger implements BuildListener { buildElement = null; } + /** + * Returns the stack of timed elements for the current thread. + * @return the stack of timed elements for the current thread + */ private Stack getStack() { Stack threadStack = (Stack)threadStacks.get(Thread.currentThread()); if (threadStack == null) { @@ -174,6 +226,14 @@ public class XmlLogger implements BuildListener { return threadStack; } + /** + * Fired when a target starts building, this pushes a timed element + * for the target onto the stack of elements for the current thread, + * rememebering the current time and the name of the target. + * + * @param event An event with any relevant extra information. + * Will not be null. + */ public void targetStarted(BuildEvent event) { Target target = event.getTarget(); TimedElement targetElement = new TimedElement(); @@ -184,6 +244,13 @@ public class XmlLogger implements BuildListener { getStack().push(targetElement); } + /** + * Fired when a target finishes building, this adds the time taken + * and any error stacktrace to the appropriate target element in the log. + * + * @param event An event with any relevant extra information. + * Will not be null. + */ public void targetFinished(BuildEvent event) { Target target = event.getTarget(); TimedElement targetElement = (TimedElement)targets.get(target); @@ -212,6 +279,14 @@ public class XmlLogger implements BuildListener { } } + /** + * Fired when a task starts building, this pushes a timed element + * for the task onto the stack of elements for the current thread, + * rememebering the current time and the name of the task. + * + * @param event An event with any relevant extra information. + * Will not be null. + */ public void taskStarted(BuildEvent event) { Task task = event.getTask(); TimedElement taskElement = new TimedElement(); @@ -225,6 +300,13 @@ public class XmlLogger implements BuildListener { getStack().push(taskElement); } + /** + * Fired when a task finishes building, this adds the time taken + * and any error stacktrace to the appropriate task element in the log. + * + * @param event An event with any relevant extra information. + * Will not be null. + */ public void taskFinished(BuildEvent event) { Task task = event.getTask(); TimedElement taskElement = (TimedElement)tasks.get(task); @@ -253,6 +335,14 @@ public class XmlLogger implements BuildListener { } } + /** + * Fired when a message is logged, this adds a message element to the + * most appropriate parent element (task, target or build) and records + * the priority and text of the message. + * + * @param event An event with any relevant extra information. + * Will not be null. + */ public void messageLogged(BuildEvent event) { Element messageElement = doc.createElement(MESSAGE_TAG); @@ -295,5 +385,4 @@ public class XmlLogger implements BuildListener { buildElement.element.appendChild(messageElement); } } - }