Source Code Cross Referenced for Log.java in  » Testing » abbot-1.0.1 » abbot » 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 » Testing » abbot 1.0.1 » abbot 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // $Id: Log.java 1912 2006-07-24 13:19:15Z twall $
002:        // Copyright (c) Oculus Technologies Corporation, all rights reserved
003:        // ----------------------------------------------------------------------------
004:        package abbot;
005:
006:        import java.io.ByteArrayOutputStream;
007:        import java.io.File;
008:        import java.io.FileOutputStream;
009:        import java.io.IOException;
010:        import java.io.OutputStream;
011:        import java.io.PrintStream;
012:        import java.lang.reflect.InvocationTargetException;
013:        import java.lang.reflect.UndeclaredThrowableException;
014:        import java.util.ArrayList;
015:        import java.util.Date;
016:        import java.util.HashMap;
017:        import java.util.HashSet;
018:        import java.util.Locale;
019:        import java.util.Map;
020:        import java.util.Set;
021:        import java.util.Vector;
022:        import abbot.util.Tee;
023:
024:        /**
025:         Various logging, assertion, and debug routines.  Typical usage is to
026:         include the following code
027:         <blockquote><code><pre>
028:         public static void main(String[] args) {
029:         &nbsp; args = Log.{@link Log#init(String[]) init}(args)
030:         &nbsp; ...
031:         }
032:         </pre></code></blockquote>
033:         at an application's main entry point.  This way the Log class can remove its
034:         options from the full set passed into the application.  See the
035:         {@link #init(String[]) Log.init} method for initialization options. <p>
036:
037:         General usage notes on public functions:<p>
038:        
039:         <ul>
040:         <li>{@link #warn(String)}<br>
041:         Programmer warnings; things that you think shouldn't be happening or
042:         indicate something might be wrong.  Warnings typically mean "Something
043:         happened that I didn't expect would happen".<p>
044:         <li>{@link #log(String)}<br>
045:         Important information that might be needed for later reference; things the
046:         user or debugger might be interested in.  By default, all messages go
047:         here.  Logs are made available so that the customer may provide us with an 
048:         accurate record of software activity.<br>
049:         All warnings and failed assertions are written to the log.  Debug
050:         statements are also written to log in non-release code.<p>
051:         <li>{@link #debug(String)}<br>
052:         Any messages which might be useful for debugging.
053:         </ul>
054:         <p>
055:        
056:         Per-class stack trace depth can be specified when adding a class, e.g.
057:         classname[:stack-depth].<p>
058:        
059:         Extraction of the stack trace and logging to file are performed on a 
060:         separate thread to minimize performance impact due to filesystem delays.
061:         Use {@link #setSynchronous(boolean) setSynchronous(false)} if you want
062:         the output to be asynchronous with program execution.<p>
063:
064:         @author      twall@users.sf.net
065:         */
066:        public class Log {
067:            /** No instantiations. */
068:            protected Log() {
069:            }
070:
071:            private static final int LOG = 0x0001;
072:            private static final int WARN = 0x0002;
073:            private static final int DEBUG = 0x0004;
074:
075:            private static final class StdErrTee extends Tee {
076:                private StdErrTee(PrintStream p1) {
077:                    super (STDERR, p1);
078:                }
079:
080:                public String toString() {
081:                    return "<stderr> and log";
082:                }
083:            }
084:
085:            private static final class StdOutTee extends Tee {
086:                private StdOutTee(PrintStream p1) {
087:                    super (STDOUT, p1);
088:                }
089:
090:                public String toString() {
091:                    return "<stdout> and log";
092:                }
093:            }
094:
095:            private static class Context extends Throwable {
096:                public Throwable thrown;
097:                public int type;
098:
099:                public Context(int type) {
100:                    this .type = type;
101:                }
102:
103:                public Context(int type, Throwable t) {
104:                    this (type);
105:                    this .thrown = t;
106:                }
107:            }
108:
109:            private static final String NL = System
110:                    .getProperty("line.separator");
111:
112:            /** Mnemonic to print all lines of a stack trace. */
113:            public static final int FULL_STACK = 0;
114:            /** No stack, just a message. */
115:            public static final int NO_STACK = -1;
116:            /** Mnemonic to print the default number of lines of stack trace. */
117:            private static final int CLASS_STACK_DEPTH = -2;
118:            private static final String STDOUT_NAME = "<stdout>";
119:            /** Basic warning categories.  FIXME use these. 
120:            public static final int ERROR   = 0x0001;
121:            public static final int WARNING = 0x0002;
122:            public static final int DEBUG   = 0x0004;
123:            public static final int INFO    = 0x0008;*/
124:
125:            /** Whether log output is synchronous */
126:            private static boolean synchronous = true;
127:            /** Whether to log messages.  Default on so that we capture output until
128:             * the log file has been set or not set in <code>#init()</code>.
129:             */
130:            private static boolean logMessages = true;
131:            /** Whether to send anything to the console. */
132:            private static boolean echoToConsole = true;
133:            private static final PrintStream STDOUT = System.out;
134:            private static final PrintStream STDERR = System.err;
135:            /** Whether to show threads in debug output. */
136:            private static boolean showThreads = false;
137:            /** Default number of lines of stack trace to print. */
138:            private static int debugStackDepth;
139:            /** Default number of lines of stack trace to log. */
140:            private static int logStackDepth;
141:            /** Default number of lines of exception stack trace to print. */
142:            private static int excStackDepth;
143:            /** Show timestamps in the log? */
144:            private static boolean showTimestamp = true;
145:            private static java.text.DateFormat timestampFormat = new java.text.SimpleDateFormat(
146:                    "yyMMdd HH:mm:ss:SSS");
147:
148:            /** Strip this out of output, since it doesn't add information to see it
149:                repeatedly. */
150:            private static final String COMMON_PREFIX = "com.oculustech.DOME.client";
151:            private static final boolean ECLIPSE = System.getProperty(
152:                    "java.class.path").indexOf("eclipse") != -1;
153:            /** Store which class names we want to see debug info for.  */
154:            private static Map debugged = new HashMap();
155:            /** Store which class names we don't want to see debug info for */
156:            private static Set notdebugged = new HashSet();
157:            /** Debug all classes? */
158:            private static boolean debugAll;
159:            /** Treat inner/anonymous classes as outer class? */
160:            private static boolean debugInner = true;
161:
162:            private static final String DEFAULT_LOGFILE_NAME = "co-log.txt";
163:            private static ByteArrayOutputStream preInitLog = new ByteArrayOutputStream();
164:            private static PrintStream logStream;
165:            /** Stream which ensures a copy goes to stdout */
166:            private static PrintStream debugStream;
167:            /** Stream which ensures a copy goes to stderr */
168:            private static PrintStream warnStream;
169:            private static LogThread logThread;
170:            private static String logFilename;
171:            private static boolean showWarnings = true;
172:            private static PrintStream BUFFER = new PrintStream(preInitLog);
173:            //private static PrintStream STDOUT_AND_BUFFER = new Tee(STDOUT, BUFFER);
174:
175:            static {
176:                setDestination(BUFFER);
177:                logThread = new LogThread();
178:                logThread.start();
179:
180:                debugStackDepth = Integer.getInteger("co.debug_stack_depth", 1)
181:                        .intValue();
182:                logStackDepth = Integer.getInteger("co.log_stack_depth",
183:                        NO_STACK).intValue();
184:                excStackDepth = Integer.getInteger("co.exception_stack_depth",
185:                        FULL_STACK).intValue();
186:
187:                // Make sure the log gets closed on System.exit
188:                Runtime.getRuntime().addShutdownHook(
189:                        new Thread("Log shutdown hook") {
190:                            public void run() {
191:                                close();
192:                            }
193:                        });
194:            }
195:
196:            /** Debug/log initialization, presumably from the command line. 
197:                <br>Recognized options:
198:                <pre>
199:                --debug all | className[:depth] | *.partialClassName[:depth]
200:                --no-debug className | *.partialClassName
201:                --log <log file name>
202:                --no-timestamp
203:                --enable-warnings
204:                --show-threads
205:                --stack-depth <depth>
206:                --exception-depth <depth>
207:                </pre>
208:             */
209:            public static String[] init(String[] args) {
210:                logMessages = false;
211:                ArrayList newArgs = new ArrayList();
212:                for (int i = 0; i < args.length; i++) {
213:                    if (args[i].equals("--enable-warnings")) {
214:                        showWarnings = true;
215:                        setEchoToConsole(true);
216:                    } else if (args[i].equals("--no-timestamp")) {
217:                        showTimestamp = false;
218:                    } else if (args[i].equals("--show-threads")) {
219:                        showThreads = true;
220:                    } else if (args[i].equals("--keep-console")) {
221:                        setEchoToConsole(true);
222:                    } else if (args[i].equals("--stack-depth")) {
223:                        if (++i < args.length) {
224:                            try {
225:                                debugStackDepth = Integer.parseInt(args[i]);
226:                            } catch (Exception exc) {
227:                            }
228:                        } else {
229:                            warn("Ignoring --stack-depth with no argument");
230:                        }
231:                    } else if (args[i].equals("--exception-depth")) {
232:                        if (++i < args.length) {
233:                            try {
234:                                excStackDepth = Integer.parseInt(args[i]);
235:                            } catch (Exception exc) {
236:                            }
237:                        } else {
238:                            warn("Ignoring --exception-depth with no argument");
239:                        }
240:                    } else if (args[i].equals("--debug")
241:                            || args[i].equals("--no-debug")) {
242:                        if (++i < args.length) {
243:                            boolean exclude = args[i].startsWith("--no");
244:                            if (exclude)
245:                                removeDebugClass(args[i]);
246:                            else {
247:                                addDebugClass(args[i]);
248:                                setEchoToConsole(true);
249:                            }
250:                        } else {
251:                            warn("Ignoring " + args[i - 1]
252:                                    + " with no argument");
253:                        }
254:                    } else if (args[i].equals("--log")) {
255:                        String filename = DEFAULT_LOGFILE_NAME;
256:                        if (++i < args.length) {
257:                            filename = args[i];
258:                        }
259:                        initLogging(filename);
260:                    } else {
261:                        newArgs.add(args[i]);
262:                    }
263:                }
264:
265:                return (String[]) newArgs.toArray(new String[newArgs.size()]);
266:            }
267:
268:            /** Is log output enabled? */
269:            public static boolean loggingInitialized() {
270:                return logMessages && logStream != null;
271:            }
272:
273:            private static String hostname = null;
274:            private static final String DEFAULT_HOSTNAME = "unknown";
275:
276:            public static String getHostName() {
277:                if (hostname == null) {
278:                    try {
279:                        hostname = java.net.InetAddress.getLocalHost()
280:                                .getHostName();
281:                    } catch (java.net.UnknownHostException e) {
282:                        hostname = DEFAULT_HOSTNAME;
283:                        warn("Cannot get hostname, using " + hostname);
284:                    }
285:                }
286:                return hostname;
287:            }
288:
289:            public static String getLogFilename() {
290:                return logFilename;
291:            }
292:
293:            public static PrintStream getLog() {
294:                return logStream;
295:            }
296:
297:            /** Enable log output to the given file.  A filename of "-" means stdout. */
298:            public static void initLogging(String filename) {
299:                PrintStream ps = STDOUT;
300:                logFilename = STDOUT_NAME;
301:                if (!"-".equals(filename) && filename != null) {
302:                    try {
303:                        ps = new PrintStream(new FileOutputStream(filename),
304:                                true);
305:                        logFilename = filename;
306:                    } catch (IOException e) {
307:                        STDERR.println("Unable to write to " + filename);
308:                        STDERR.println("Output will go to the console");
309:                    }
310:                }
311:
312:                setDestination(ps);
313:
314:                log("Log started on " + getHostName() + " (directed to "
315:                        + logFilename + ")");
316:                // Always insert the system information
317:                Log.log(getSystemInfo());
318:            }
319:
320:            /** Enable log output to the given {@link PrintStream}. */
321:            public static void setDestination(PrintStream ps) {
322:                logMessages = true;
323:                logStream = ps;
324:                // If there's a log file, redirect stdout/stderr there
325:                if (logStream == STDOUT) {
326:                    debugStream = logStream;
327:                    warnStream = STDERR;
328:                } else if (logStream == BUFFER) {
329:                    debugStream = new StdOutTee(BUFFER);
330:                    warnStream = new StdErrTee(BUFFER);
331:                } else {
332:                    if (preInitLog.size() > 0) {
333:                        ps.print(preInitLog.toString());
334:                        preInitLog.reset();
335:                    }
336:                    debugStream = new StdOutTee(logStream);
337:                    warnStream = new StdErrTee(logStream);
338:                    System.setErr(warnStream);
339:                    System.setOut(debugStream);
340:                    if (logFilename != null) {
341:                        File file = new File(logFilename);
342:                        STDOUT
343:                                .println("Output also captured in the log file at "
344:                                        + file.getAbsolutePath());
345:                    }
346:                }
347:                setEchoToConsole(logStream != STDOUT);
348:            }
349:
350:            public static String getSystemInfo() {
351:                Locale loc = Locale.getDefault();
352:                return "System Details:" + NL + "     java: "
353:                        + System.getProperty("java.vm.name") + " "
354:                        + System.getProperty("java.vm.version") + NL
355:                        + "       os: " + System.getProperty("os.name") + " "
356:                        + System.getProperty("os.version") + " "
357:                        + System.getProperty("os.arch") + NL + " user.dir: "
358:                        + System.getProperty("user.dir") + NL + "   locale: "
359:                        + loc.getDisplayName() + " " + "[" + loc.getLanguage()
360:                        + " " + loc.getCountry() + "]" + NL + "classpath: "
361:                        + System.getProperty("java.class.path");
362:            }
363:
364:            /** Sets the debug stack depth to the given amount */
365:            public static void setDebugStackDepth(int depth) {
366:                debugStackDepth = depth;
367:            }
368:
369:            /** Resets the lists of classes to debug and not debug to be
370:                empty, and turns debugAll off.  
371:             */
372:            public static void clearDebugClasses() {
373:                debugged.clear();
374:                debugAll = false;
375:                notdebugged.clear();
376:            }
377:
378:            /** Indicate that the given class should NOT be debugged 
379:                (assuming --debug all) */
380:            public static void removeDebugClass(String className) {
381:                setClassDebugEnabled(className, false);
382:            }
383:
384:            /** Indicate that debug messages should be output for the given class. */
385:            public static void addDebugClass(Class class1) {
386:                addDebugClass(class1.getName());
387:            }
388:
389:            /** Indicate that debug messages should no longer be output for the given 
390:             * class. 
391:             */
392:            public static void removeDebugClass(Class class1) {
393:                removeDebugClass(class1.getName());
394:            }
395:
396:            /** Indicate the class name[:depth] to add to debug output. */
397:            public static void addDebugClass(String className) {
398:                if (className.indexOf(":") == -1)
399:                    addDebugClass(className, CLASS_STACK_DEPTH);
400:                else
401:                    setClassDebugEnabled(className, true);
402:            }
403:
404:            /** Indicate that debug messages should be output for the given class. */
405:            public static void addDebugClass(String className, int depth) {
406:                setClassDebugEnabled(className + ":" + depth, true);
407:            }
408:
409:            /** Parse the given string, which may should be of the format
410:                "class[:depth]" */
411:            private static void setClassDebugEnabled(String id, boolean enable) {
412:                int colon = id.indexOf(":");
413:                String className = colon == -1 ? id : id.substring(0, colon);
414:                if ("all".equals(className)) {
415:                    debugAll = enable;
416:                    if (enable) {
417:                        notdebugged.clear();
418:                    } else {
419:                        debugged.clear();
420:                    }
421:                } else {
422:                    className = getFullClassName(className);
423:                    int depth = CLASS_STACK_DEPTH;
424:                    try {
425:                        depth = colon == -1 ? debugStackDepth : Integer
426:                                .parseInt(id.substring(colon + 1));
427:                    } catch (NumberFormatException nfe) {
428:                    }
429:                    if (enable) {
430:                        debugged.put(className, new Integer(depth));
431:                        notdebugged.remove(className);
432:                        debug("Debugging enabled for " + className + " ("
433:                                + depth + ")");
434:                    } else {
435:                        notdebugged.add(className);
436:                        debugged.remove(className);
437:                        debug("Debugging disabled for " + className);
438:                    }
439:                }
440:            }
441:
442:            /** Returns class from given name/descriptor.  Descriptor can be either a
443:                fully qualified classname, or a classname beginning with *. with
444:                client-specific package and classname following.
445:             */
446:            private static String getFullClassName(String className) {
447:                if (COMMON_PREFIX != null && className.startsWith("*.")) {
448:                    className = COMMON_PREFIX + className.substring(1);
449:                }
450:                return className;
451:            }
452:
453:            /** Return the requested number of levels of stack trace, not including
454:                this call.   Returns the full stack trace if LINES is FULL_STACK.
455:                Skip the first POP frames of the trace, which is for excluding the
456:                innermost stack frames when debug functions make nested calls.
457:                The outermost call of getStackTrace itself is always removed from the
458:                trace.  */
459:            private static String getStackTrace(int pop, int lines) {
460:                return getStackTrace(pop, lines, new Throwable("--debug--"));
461:            }
462:
463:            /** Return the requested number of levels of stack trace, not including
464:                this call.   Returns the full stack trace if LINES is FULL_STACK.
465:                Skip the first POP frames of the trace, which is for excluding the
466:                innermost stack frames when debug functions make nested calls.
467:                The outermost call of getStackTrace itself is always removed from the
468:                trace.   Provide an exception to use for the stack trace,
469:                rather than using the current program location.
470:             */
471:            private static String getStackTrace(int pop, int lines,
472:                    Throwable thr) {
473:                if (lines != NO_STACK) {
474:                    String stack = getStackTrace(pop, thr);
475:                    if (lines == FULL_STACK)
476:                        return stack;
477:                    return trimStackTrace(stack, lines);
478:                }
479:                return "";
480:            }
481:
482:            /** Return the stack trace contained in the given Throwable.
483:                Skip the first POP frames of the trace, which is for excluding the
484:                innermost stack frames when debug functions make nested calls.
485:                The outermost call of getStackTrace itself is always removed from the
486:                trace.   
487:             */
488:            private static String getStackTrace(int pop, Throwable thr) {
489:                OutputStream os = new ByteArrayOutputStream();
490:                PrintStream newStream = new PrintStream(os, true);
491:                // OUCH! this is a serious performance hit!
492:                thr.printStackTrace(newStream);
493:                String trace = os.toString();
494:
495:                // Pop off getStackTrace itself
496:                // Skip over any calls to getStackTrace; the JIT sometimes puts a
497:                // spurious entry, so don't just stop at the first one.
498:                int getLoc = trace.lastIndexOf("getStackTrace");
499:                int at = trace.indexOf("\tat ", getLoc);
500:                if (at != -1)
501:                    trace = trace.substring(at + 3);
502:                while (pop-- > 0) {
503:                    // pop off the calling function
504:                    at = trace.indexOf("\tat ");
505:                    if (at != -1)
506:                        trace = trace.substring(at + 3);
507:                }
508:
509:                return trace.trim();
510:            }
511:
512:            /** Trim the given trace to LINES levels. */
513:            private static String trimStackTrace(String trace, int lines) {
514:                // Keep just as many lines as were requested
515:                int end = trace.indexOf(")") + 1;
516:                boolean all = (lines == FULL_STACK);
517:                while (all || --lines > 0) {
518:                    int index = trace.indexOf("\tat ", end);
519:                    if (index < 0)
520:                        break;
521:                    end = trace.indexOf(")", index) + 1;
522:                }
523:                return trace.substring(0, end);
524:            }
525:
526:            /** Return the class corresponding to the first line in the give stack
527:                trace.  Treat inner/anonymous classes as the enclosing class. */
528:            // FIXME with JIT enabled, stack trace sometimes has spurious junk on the
529:            // stack, which will indicate the wrong class...
530:            private static String extractClass(String trace) {
531:                int paren = trace.indexOf("(");
532:                String tmp = paren == -1 ? trace : trace.substring(0, paren);
533:                int mstart = tmp.lastIndexOf(".");
534:                String cname = mstart == -1 ? tmp : tmp.substring(0, mstart);
535:                cname = cname.trim();
536:                if (debugInner) {
537:                    int sub = cname.indexOf("$");
538:                    if (sub != -1)
539:                        cname = cname.substring(0, sub).trim();
540:                }
541:
542:                return cname;
543:            }
544:
545:            public static boolean isClassDebugEnabled(Class cls) {
546:                return isClassDebugEnabled(cls.getName());
547:            }
548:
549:            public static boolean isClassDebugEnabled(String className) {
550:                return (debugAll || debugged.containsKey(className))
551:                        && !notdebugged.contains(className);
552:            }
553:
554:            static int getClassStackDepth(String cname) {
555:                Integer depth = (Integer) debugged.get(cname);
556:                if (depth != null && depth.intValue() != CLASS_STACK_DEPTH)
557:                    return depth.intValue();
558:                return debugStackDepth;
559:            }
560:
561:            /** Print a debug message. */
562:            public static void debug(String event) {
563:                internalDebug(event, new Context(DEBUG));
564:            }
565:
566:            /** Print a debug message with the given number of stack lines. */
567:            public static void debug(String event, int lines) {
568:                internalDebug(event, new Context(DEBUG), lines);
569:            }
570:
571:            /** Use this to display debug output for expected or common exceptions. */
572:            public static void debug(Throwable thr) {
573:                internalDebug("", new Context(DEBUG, thr));
574:            }
575:
576:            /** Issue a debug statement regarding the given {@link Throwable}. */
577:            public static void debug(String m, Throwable e) {
578:                internalDebug(m, new Context(DEBUG, e));
579:            }
580:
581:            private static void internalDebug(String msg, Context context) {
582:                internalDebug(msg, context, CLASS_STACK_DEPTH);
583:            }
584:
585:            private static void internalDebug(String msg, Context context,
586:                    int lines) {
587:                if (debugged.size() > 0 || debugAll) {
588:                    internalLog(msg, context, lines, 1,
589:                            echoToConsole ? debugStream : logStream);
590:                }
591:            }
592:
593:            /** Replace all occurrences of a given expresion with a different
594:                string. */
595:            private static String abbreviate(String msg, String expr, String sub) {
596:                // Eclipse uses the full classs name for navigation, so don't hide it
597:                if (ECLIPSE)
598:                    return msg;
599:                StringBuffer sb = new StringBuffer(msg);
600:                int index = msg.indexOf(expr);
601:                int len = expr.length();
602:                while (index >= 0) {
603:                    sb.replace(index, index + len, sub);
604:                    index = sb.toString().indexOf(expr);
605:                }
606:                return sb.toString();
607:            }
608:
609:            /** Strip out stuff we don't want showing in the message.  */
610:            private static String abbreviate(String msg) {
611:                if (COMMON_PREFIX != null)
612:                    msg = abbreviate(msg, COMMON_PREFIX, "*");
613:                return msg;
614:            }
615:
616:            /** Issue a warning.  All warnings go to the log file and the error
617:                stream. */
618:            private static void internalWarn(String message, Context context,
619:                    int depth, int pop) {
620:                internalLog(message, context, depth, pop,
621:                        showWarnings ? warnStream : logStream);
622:            }
623:
624:            /** Retrieve the given number of lines of the current stack, as a
625:                string. */
626:            public static String getStack(int lines) {
627:                return getStackTrace(1, lines);
628:            }
629:
630:            /** Retrieve the full stack from the given Throwable, as a string. */
631:            public static String getStack(Throwable t) {
632:                return getStackTrace(Log.FULL_STACK, t);
633:            }
634:
635:            /** Retrieve the given number of lines of stack from the given Throwable,
636:                as a string. */
637:            public static String getStack(int lines, Throwable thr) {
638:                return getStackTrace(1, lines, thr);
639:            }
640:
641:            /** Issue a programmer warning, which will include the source line of the 
642:                warning. */
643:            public static void warn(String message) {
644:                internalWarn(message, new Context(WARN), debugStackDepth, 1);
645:            }
646:
647:            /** Issue a programmer warning, which will include the source line of the 
648:                warning. */
649:            public static void warn(String message, Throwable e) {
650:                internalWarn(message, new Context(WARN, e), debugStackDepth, 1);
651:            }
652:
653:            /** Issue a programmer warning, which will include the source line of the 
654:                warning, and a stack trace with up to the given number of lines. */
655:            public static void warn(String message, int lines) {
656:                internalWarn(message, new Context(WARN), lines, 1);
657:            }
658:
659:            /** Issue a programmer warning, which will include the source line of the 
660:                original thrown object. */
661:            public static void warn(Throwable thr) {
662:                internalWarn("", new Context(WARN, thr), debugStackDepth, 1);
663:            }
664:
665:            /** Log an exception. */
666:            public static void log(Throwable thr) {
667:                internalLog("", new Context(LOG, thr), excStackDepth, 1);
668:            }
669:
670:            /** Log an exception with a description. */
671:            public static void log(String message, Throwable thr) {
672:                internalLog(message, new Context(LOG, thr), excStackDepth, 1);
673:            }
674:
675:            /** Log a message. */
676:            public static void log(String message) {
677:                internalLog(message, new Context(LOG), logStackDepth, 1);
678:            }
679:
680:            private static void internalLog(String event, Context context,
681:                    int depth, int pop) {
682:                internalLog(event, context, depth, pop, logStream);
683:            }
684:
685:            private static void internalLog(String event, Context context,
686:                    int depth, int pop, PrintStream stream) {
687:                String thread = Thread.currentThread().getName();
688:                if (synchronous) {
689:                    logMessage(event, new Date(), context, depth, pop, stream,
690:                            thread);
691:                } else if (logThread != null) {
692:                    logThread.post(event, thread, new Date(), context, depth,
693:                            pop, stream);
694:                } else {
695:                    STDERR.println("Message posted after close: " + event);
696:                }
697:            }
698:
699:            static void flush() {
700:                while (logThread.queue.size() > 0) {
701:                    synchronized (logThread.queue) {
702:                        logThread.queue.notifyAll();
703:                    }
704:                    try {
705:                        Thread.sleep(10);
706:                    } catch (InterruptedException e) {
707:                    }
708:                }
709:                debugStream.flush();
710:                warnStream.flush();
711:                logStream.flush();
712:            }
713:
714:            public static void close() {
715:                flush();
716:                log("Log closed");
717:                logStream.close();
718:                logThread.terminate();
719:                logThread = null;
720:            }
721:
722:            private static class LogThread extends Thread {
723:                private boolean terminate;
724:                private Vector queue = new Vector();
725:
726:                public LogThread() {
727:                    super ("Logging thread");
728:                    setDaemon(true);
729:                }
730:
731:                public void terminate() {
732:                    synchronized (queue) {
733:                        terminate = true;
734:                        queue.notifyAll();
735:                    }
736:                }
737:
738:                public void post(String msg, String threadName, Date date,
739:                        Context throwable, int depth, int pop,
740:                        PrintStream output) {
741:                    synchronized (queue) {
742:                        if (!terminate) {
743:                            queue.add(new Object[] { msg, date, throwable,
744:                                    new int[] { depth, pop }, output,
745:                                    threadName });
746:                            queue.notifyAll();
747:                        } else {
748:                            STDERR.println("discarded: " + msg);
749:                        }
750:                    }
751:                }
752:
753:                public void run() {
754:                    setName("Logging thread (to " + logStream + ")");
755:                    while (!terminate) {
756:                        try {
757:                            while (queue.size() > 0) {
758:                                Object[] list = (Object[]) queue.get(0);
759:                                int[] args = (int[]) list[3];
760:                                logMessage((String) list[0], (Date) list[1],
761:                                        (Context) list[2], args[0], args[1],
762:                                        (PrintStream) list[4], (String) list[5]);
763:                                queue.remove(0);
764:                            }
765:                            synchronized (queue) {
766:                                if (queue.size() == 0) {
767:                                    queue.wait();
768:                                }
769:                            }
770:                        } catch (InterruptedException e) {
771:                            break;
772:                        } catch (Throwable e) {
773:                            STDERR.println("Error in logging thread: " + e);
774:                            e.printStackTrace();
775:                        }
776:                    }
777:                }
778:            }
779:
780:            private static String lastMessage = null;
781:            private static int lastMessageRepeatCount = 0;
782:            private static String lastMessageTimestamp = null;
783:            private static PrintStream lastMessageStream = null;
784:
785:            private static void logMessage(String msg, Date date,
786:                    Context context, int depth, int pop, PrintStream stream,
787:                    String threadName) {
788:                boolean debug = context.type == DEBUG;
789:                String trace;
790:                if (debug) {
791:                    trace = getStackTrace(pop, Log.FULL_STACK, context);
792:                    String cname = extractClass(trace);
793:                    if (!isClassDebugEnabled(cname)) {
794:                        return;
795:                    }
796:                    if (depth == CLASS_STACK_DEPTH) {
797:                        trace = trimStackTrace(trace, getClassStackDepth(cname));
798:                    }
799:                } else {
800:                    trace = getStackTrace(pop, depth, context);
801:                }
802:                if (context.thrown != null) {
803:                    Throwable e = context.thrown;
804:                    String where = getStackTrace(0, excStackDepth, e);
805:                    String type = e instanceof  Error ? "Error"
806:                            : "Exception thrown";
807:                    trace = type + " at " + where + ": " + e + NL
808:                            + "\t(caught at " + trace + ")";
809:                    if (e instanceof  InvocationTargetException) {
810:                        e = ((InvocationTargetException) e)
811:                                .getTargetException();
812:                        where = getStackTrace(0, excStackDepth, e);
813:                        trace += NL + "Target exception was " + e + " at "
814:                                + where;
815:                    } else if (e instanceof  UndeclaredThrowableException) {
816:                        e = ((UndeclaredThrowableException) e)
817:                                .getUndeclaredThrowable();
818:                        where = getStackTrace(0, excStackDepth, e);
819:                        trace += NL + "Undeclared exception was " + e + " at "
820:                                + where;
821:                    } else if (e instanceof  ExceptionInInitializerError) {
822:                        e = ((ExceptionInInitializerError) e).getException();
823:                        where = getStackTrace(0, excStackDepth, e);
824:                        trace += NL + "Exception was " + e + " at " + where;
825:                    }
826:                }
827:                trace = abbreviate(trace);
828:                if (showThreads) {
829:                    trace = "[" + threadName + "] " + trace;
830:                }
831:                String timestamp = timestampFormat.format(date);
832:                if (showTimestamp) {
833:                    trace = timestamp + " " + trace;
834:                }
835:                String output = trace.trim();
836:                if (msg != null && !"".equals(msg)) {
837:                    output += ":\n\t" + msg;
838:                }
839:                if (stream == lastMessageStream
840:                        && (msg == lastMessage || (msg != null && msg
841:                                .equals(lastMessage)))) {
842:                    ++lastMessageRepeatCount;
843:                    lastMessageTimestamp = timestamp;
844:                } else {
845:                    if (lastMessageRepeatCount > 0) {
846:                        lastMessageStream.println(lastMessageTimestamp
847:                                + ": Last message repeated "
848:                                + lastMessageRepeatCount + " times");
849:                        lastMessageStream.flush();
850:                    }
851:                    stream.println(output);
852:                    lastMessage = msg;
853:                    lastMessageStream = stream;
854:                    lastMessageRepeatCount = 0;
855:                    lastMessageTimestamp = timestamp;
856:                }
857:            }
858:
859:            /** Set whether log output is synchronous with program execution. */
860:            public static void setSynchronous(boolean b) {
861:                synchronous = b;
862:            }
863:
864:            /** Set whether to display the current thread of execution. */
865:            public static void setShowThreads(boolean b) {
866:                showThreads = b;
867:            }
868:
869:            /** Set whether messages are echoed to the console in addition to the log. 
870:             */
871:            public static void setEchoToConsole(boolean b) {
872:                echoToConsole = b;
873:            }
874:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.