Source Code Cross Referenced for XmlLogger.java in  » Build » ANT » org » apache » tools » ant » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Build » ANT » org.apache.tools.ant 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
003:         *  contributor license agreements.  See the NOTICE file distributed with
004:         *  this work for additional information regarding copyright ownership.
005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
006:         *  (the "License"); you may not use this file except in compliance with
007:         *  the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         *  Unless required by applicable law or agreed to in writing, software
012:         *  distributed under the License is distributed on an "AS IS" BASIS,
013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         *  See the License for the specific language governing permissions and
015:         *  limitations under the License.
016:         *
017:         */
018:
019:        package org.apache.tools.ant;
020:
021:        import java.io.FileOutputStream;
022:        import java.io.IOException;
023:        import java.io.OutputStream;
024:        import java.io.OutputStreamWriter;
025:        import java.io.PrintStream;
026:        import java.io.Writer;
027:        import java.util.Hashtable;
028:        import java.util.Stack;
029:        import java.util.Enumeration;
030:        import javax.xml.parsers.DocumentBuilder;
031:        import javax.xml.parsers.DocumentBuilderFactory;
032:        import org.apache.tools.ant.util.DOMElementWriter;
033:        import org.apache.tools.ant.util.StringUtils;
034:        import org.w3c.dom.Document;
035:        import org.w3c.dom.Element;
036:        import org.w3c.dom.Text;
037:
038:        /**
039:         * Generates a file in the current directory with
040:         * an XML description of what happened during a build.
041:         * The default filename is "log.xml", but this can be overridden
042:         * with the property <code>XmlLogger.file</code>.
043:         *
044:         * This implementation assumes in its sanity checking that only one
045:         * thread runs a particular target/task at a time. This is enforced
046:         * by the way that parallel builds and antcalls are done - and
047:         * indeed all but the simplest of tasks could run into problems
048:         * if executed in parallel.
049:         *
050:         * @see Project#addBuildListener(BuildListener)
051:         */
052:        public class XmlLogger implements  BuildLogger {
053:
054:            private int msgOutputLevel = Project.MSG_DEBUG;
055:            private PrintStream outStream;
056:
057:            /** DocumentBuilder to use when creating the document to start with. */
058:            private static DocumentBuilder builder = getDocumentBuilder();
059:
060:            /**
061:             * Returns a default DocumentBuilder instance or throws an
062:             * ExceptionInInitializerError if it can't be created.
063:             *
064:             * @return a default DocumentBuilder instance.
065:             */
066:            private static DocumentBuilder getDocumentBuilder() {
067:                try {
068:                    return DocumentBuilderFactory.newInstance()
069:                            .newDocumentBuilder();
070:                } catch (Exception exc) {
071:                    throw new ExceptionInInitializerError(exc);
072:                }
073:            }
074:
075:            /** XML element name for a build. */
076:            private static final String BUILD_TAG = "build";
077:            /** XML element name for a target. */
078:            private static final String TARGET_TAG = "target";
079:            /** XML element name for a task. */
080:            private static final String TASK_TAG = "task";
081:            /** XML element name for a message. */
082:            private static final String MESSAGE_TAG = "message";
083:            /** XML attribute name for a name. */
084:            private static final String NAME_ATTR = "name";
085:            /** XML attribute name for a time. */
086:            private static final String TIME_ATTR = "time";
087:            /** XML attribute name for a message priority. */
088:            private static final String PRIORITY_ATTR = "priority";
089:            /** XML attribute name for a file location. */
090:            private static final String LOCATION_ATTR = "location";
091:            /** XML attribute name for an error description. */
092:            private static final String ERROR_ATTR = "error";
093:            /** XML element name for a stack trace. */
094:            private static final String STACKTRACE_TAG = "stacktrace";
095:
096:            /** The complete log document for this build. */
097:            private Document doc = builder.newDocument();
098:            /** Mapping for when tasks started (Task to TimedElement). */
099:            private Hashtable tasks = new Hashtable();
100:            /** Mapping for when targets started (Task to TimedElement). */
101:            private Hashtable targets = new Hashtable();
102:            /**
103:             * Mapping of threads to stacks of elements
104:             * (Thread to Stack of TimedElement).
105:             */
106:            private Hashtable threadStacks = new Hashtable();
107:            /**
108:             * When the build started.
109:             */
110:            private TimedElement buildElement = null;
111:
112:            /** Utility class representing the time an element started. */
113:            private static class TimedElement {
114:                /**
115:                 * Start time in milliseconds
116:                 * (as returned by <code>System.currentTimeMillis()</code>).
117:                 */
118:                private long startTime;
119:                /** Element created at the start time. */
120:                private Element element;
121:
122:                public String toString() {
123:                    return element.getTagName() + ":"
124:                            + element.getAttribute("name");
125:                }
126:            }
127:
128:            /**
129:             *  Constructs a new BuildListener that logs build events to an XML file.
130:             */
131:            public XmlLogger() {
132:            }
133:
134:            /**
135:             * Fired when the build starts, this builds the top-level element for the
136:             * document and remembers the time of the start of the build.
137:             *
138:             * @param event Ignored.
139:             */
140:            public void buildStarted(BuildEvent event) {
141:                buildElement = new TimedElement();
142:                buildElement.startTime = System.currentTimeMillis();
143:                buildElement.element = doc.createElement(BUILD_TAG);
144:            }
145:
146:            /**
147:             * Fired when the build finishes, this adds the time taken and any
148:             * error stacktrace to the build element and writes the document to disk.
149:             *
150:             * @param event An event with any relevant extra information.
151:             *              Will not be <code>null</code>.
152:             */
153:            public void buildFinished(BuildEvent event) {
154:                long totalTime = System.currentTimeMillis()
155:                        - buildElement.startTime;
156:                buildElement.element.setAttribute(TIME_ATTR, DefaultLogger
157:                        .formatTime(totalTime));
158:
159:                if (event.getException() != null) {
160:                    buildElement.element.setAttribute(ERROR_ATTR, event
161:                            .getException().toString());
162:                    // print the stacktrace in the build file it is always useful...
163:                    // better have too much info than not enough.
164:                    Throwable t = event.getException();
165:                    Text errText = doc.createCDATASection(StringUtils
166:                            .getStackTrace(t));
167:                    Element stacktrace = doc.createElement(STACKTRACE_TAG);
168:                    stacktrace.appendChild(errText);
169:                    buildElement.element.appendChild(stacktrace);
170:                }
171:
172:                String outFilename = event.getProject().getProperty(
173:                        "XmlLogger.file");
174:                if (outFilename == null) {
175:                    outFilename = "log.xml";
176:                }
177:                String xslUri = event.getProject().getProperty(
178:                        "ant.XmlLogger.stylesheet.uri");
179:                if (xslUri == null) {
180:                    xslUri = "log.xsl";
181:                }
182:                Writer out = null;
183:                try {
184:                    // specify output in UTF8 otherwise accented characters will blow
185:                    // up everything
186:                    OutputStream stream = outStream;
187:                    if (stream == null) {
188:                        stream = new FileOutputStream(outFilename);
189:                    }
190:                    out = new OutputStreamWriter(stream, "UTF8");
191:                    out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
192:                    if (xslUri.length() > 0) {
193:                        out.write("<?xml-stylesheet type=\"text/xsl\" href=\""
194:                                + xslUri + "\"?>\n\n");
195:                    }
196:                    (new DOMElementWriter()).write(buildElement.element, out,
197:                            0, "\t");
198:                    out.flush();
199:                } catch (IOException exc) {
200:                    throw new BuildException("Unable to write log file", exc);
201:                } finally {
202:                    if (out != null) {
203:                        try {
204:                            out.close();
205:                        } catch (IOException e) {
206:                            // ignore
207:                        }
208:                    }
209:                }
210:                buildElement = null;
211:            }
212:
213:            /**
214:             * Returns the stack of timed elements for the current thread.
215:             * @return the stack of timed elements for the current thread
216:             */
217:            private Stack getStack() {
218:                Stack threadStack = (Stack) threadStacks.get(Thread
219:                        .currentThread());
220:                if (threadStack == null) {
221:                    threadStack = new Stack();
222:                    threadStacks.put(Thread.currentThread(), threadStack);
223:                }
224:                /* For debugging purposes uncomment:
225:                org.w3c.dom.Comment s = doc.createComment("stack=" + threadStack);
226:                buildElement.element.appendChild(s);
227:                 */
228:                return threadStack;
229:            }
230:
231:            /**
232:             * Fired when a target starts building, this pushes a timed element
233:             * for the target onto the stack of elements for the current thread,
234:             * remembering the current time and the name of the target.
235:             *
236:             * @param event An event with any relevant extra information.
237:             *              Will not be <code>null</code>.
238:             */
239:            public void targetStarted(BuildEvent event) {
240:                Target target = event.getTarget();
241:                TimedElement targetElement = new TimedElement();
242:                targetElement.startTime = System.currentTimeMillis();
243:                targetElement.element = doc.createElement(TARGET_TAG);
244:                targetElement.element.setAttribute(NAME_ATTR, target.getName());
245:                targets.put(target, targetElement);
246:                getStack().push(targetElement);
247:            }
248:
249:            /**
250:             * Fired when a target finishes building, this adds the time taken
251:             * and any error stacktrace to the appropriate target element in the log.
252:             *
253:             * @param event An event with any relevant extra information.
254:             *              Will not be <code>null</code>.
255:             */
256:            public void targetFinished(BuildEvent event) {
257:                Target target = event.getTarget();
258:                TimedElement targetElement = (TimedElement) targets.get(target);
259:                if (targetElement != null) {
260:                    long totalTime = System.currentTimeMillis()
261:                            - targetElement.startTime;
262:                    targetElement.element.setAttribute(TIME_ATTR, DefaultLogger
263:                            .formatTime(totalTime));
264:
265:                    TimedElement parentElement = null;
266:                    Stack threadStack = getStack();
267:                    if (!threadStack.empty()) {
268:                        TimedElement poppedStack = (TimedElement) threadStack
269:                                .pop();
270:                        if (poppedStack != targetElement) {
271:                            throw new RuntimeException(
272:                                    "Mismatch - popped element = "
273:                                            + poppedStack
274:                                            + " finished target element = "
275:                                            + targetElement);
276:                        }
277:                        if (!threadStack.empty()) {
278:                            parentElement = (TimedElement) threadStack.peek();
279:                        }
280:                    }
281:                    if (parentElement == null) {
282:                        buildElement.element.appendChild(targetElement.element);
283:                    } else {
284:                        parentElement.element
285:                                .appendChild(targetElement.element);
286:                    }
287:                }
288:                targets.remove(target);
289:            }
290:
291:            /**
292:             * Fired when a task starts building, this pushes a timed element
293:             * for the task onto the stack of elements for the current thread,
294:             * remembering the current time and the name of the task.
295:             *
296:             * @param event An event with any relevant extra information.
297:             *              Will not be <code>null</code>.
298:             */
299:            public void taskStarted(BuildEvent event) {
300:                TimedElement taskElement = new TimedElement();
301:                taskElement.startTime = System.currentTimeMillis();
302:                taskElement.element = doc.createElement(TASK_TAG);
303:
304:                Task task = event.getTask();
305:                String name = event.getTask().getTaskName();
306:                if (name == null) {
307:                    name = "";
308:                }
309:                taskElement.element.setAttribute(NAME_ATTR, name);
310:                taskElement.element.setAttribute(LOCATION_ATTR, event.getTask()
311:                        .getLocation().toString());
312:                tasks.put(task, taskElement);
313:                getStack().push(taskElement);
314:            }
315:
316:            /**
317:             * Fired when a task finishes building, this adds the time taken
318:             * and any error stacktrace to the appropriate task element in the log.
319:             *
320:             * @param event An event with any relevant extra information.
321:             *              Will not be <code>null</code>.
322:             */
323:            public void taskFinished(BuildEvent event) {
324:                Task task = event.getTask();
325:                TimedElement taskElement = (TimedElement) tasks.get(task);
326:                if (taskElement != null) {
327:                    long totalTime = System.currentTimeMillis()
328:                            - taskElement.startTime;
329:                    taskElement.element.setAttribute(TIME_ATTR, DefaultLogger
330:                            .formatTime(totalTime));
331:                    Target target = task.getOwningTarget();
332:                    TimedElement targetElement = null;
333:                    if (target != null) {
334:                        targetElement = (TimedElement) targets.get(target);
335:                    }
336:                    if (targetElement == null) {
337:                        buildElement.element.appendChild(taskElement.element);
338:                    } else {
339:                        targetElement.element.appendChild(taskElement.element);
340:                    }
341:                    Stack threadStack = getStack();
342:                    if (!threadStack.empty()) {
343:                        TimedElement poppedStack = (TimedElement) threadStack
344:                                .pop();
345:                        if (poppedStack != taskElement) {
346:                            throw new RuntimeException(
347:                                    "Mismatch - popped element = "
348:                                            + poppedStack
349:                                            + " finished task element = "
350:                                            + taskElement);
351:                        }
352:                    }
353:                    tasks.remove(task);
354:                } else {
355:                    throw new RuntimeException("Unknown task " + task
356:                            + " not in " + tasks);
357:                }
358:            }
359:
360:            /**
361:             * Get the TimedElement associated with a task.
362:             *
363:             * Where the task is not found directly, search for unknown elements which
364:             * may be hiding the real task
365:             */
366:            private TimedElement getTaskElement(Task task) {
367:                TimedElement element = (TimedElement) tasks.get(task);
368:                if (element != null) {
369:                    return element;
370:                }
371:
372:                for (Enumeration e = tasks.keys(); e.hasMoreElements();) {
373:                    Task key = (Task) e.nextElement();
374:                    if (key instanceof  UnknownElement) {
375:                        if (((UnknownElement) key).getTask() == task) {
376:                            return (TimedElement) tasks.get(key);
377:                        }
378:                    }
379:                }
380:
381:                return null;
382:            }
383:
384:            /**
385:             * Fired when a message is logged, this adds a message element to the
386:             * most appropriate parent element (task, target or build) and records
387:             * the priority and text of the message.
388:             *
389:             * @param event An event with any relevant extra information.
390:             *              Will not be <code>null</code>.
391:             */
392:            public void messageLogged(BuildEvent event) {
393:                int priority = event.getPriority();
394:                if (priority > msgOutputLevel) {
395:                    return;
396:                }
397:                Element messageElement = doc.createElement(MESSAGE_TAG);
398:
399:                String name = "debug";
400:                switch (event.getPriority()) {
401:                case Project.MSG_ERR:
402:                    name = "error";
403:                    break;
404:                case Project.MSG_WARN:
405:                    name = "warn";
406:                    break;
407:                case Project.MSG_INFO:
408:                    name = "info";
409:                    break;
410:                default:
411:                    name = "debug";
412:                    break;
413:                }
414:                messageElement.setAttribute(PRIORITY_ATTR, name);
415:
416:                Throwable ex = event.getException();
417:                if (Project.MSG_DEBUG <= msgOutputLevel && ex != null) {
418:                    Text errText = doc.createCDATASection(StringUtils
419:                            .getStackTrace(ex));
420:                    Element stacktrace = doc.createElement(STACKTRACE_TAG);
421:                    stacktrace.appendChild(errText);
422:                    buildElement.element.appendChild(stacktrace);
423:                }
424:                Text messageText = doc.createCDATASection(event.getMessage());
425:                messageElement.appendChild(messageText);
426:
427:                TimedElement parentElement = null;
428:
429:                Task task = event.getTask();
430:
431:                Target target = event.getTarget();
432:                if (task != null) {
433:                    parentElement = getTaskElement(task);
434:                }
435:                if (parentElement == null && target != null) {
436:                    parentElement = (TimedElement) targets.get(target);
437:                }
438:
439:                /*
440:                if (parentElement == null) {
441:                    Stack threadStack
442:                            = (Stack) threadStacks.get(Thread.currentThread());
443:                    if (threadStack != null) {
444:                        if (!threadStack.empty()) {
445:                            parentElement = (TimedElement) threadStack.peek();
446:                        }
447:                    }
448:                }
449:                 */
450:
451:                if (parentElement != null) {
452:                    parentElement.element.appendChild(messageElement);
453:                } else {
454:                    buildElement.element.appendChild(messageElement);
455:                }
456:            }
457:
458:            // -------------------------------------------------- BuildLogger interface
459:
460:            /**
461:             * Set the logging level when using this as a Logger
462:             *
463:             * @param level the logging level -
464:             *        see {@link org.apache.tools.ant.Project#MSG_ERR Project}
465:             *        class for level definitions
466:             */
467:            public void setMessageOutputLevel(int level) {
468:                msgOutputLevel = level;
469:            }
470:
471:            /**
472:             * Set the output stream to which logging output is sent when operating
473:             * as a logger.
474:             *
475:             * @param output the output PrintStream.
476:             */
477:            public void setOutputPrintStream(PrintStream output) {
478:                this .outStream = new PrintStream(output, true);
479:            }
480:
481:            /**
482:             * Ignore emacs mode, as it has no meaning in XML format
483:             *
484:             * @param emacsMode true if logger should produce emacs compatible
485:             *        output
486:             */
487:            public void setEmacsMode(boolean emacsMode) {
488:            }
489:
490:            /**
491:             * Ignore error print stream. All output will be written to
492:             * either the XML log file or the PrintStream provided to
493:             * setOutputPrintStream
494:             *
495:             * @param err the stream we are going to ignore.
496:             */
497:            public void setErrorPrintStream(PrintStream err) {
498:            }
499:
500:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.