001    /*
002     * Copyright (c) 2003, The Regents of the University of California, through
003     * Lawrence Berkeley National Laboratory (subject to receipt of any required
004     * approvals from the U.S. Dept. of Energy). All rights reserved.
005     */
006    package gov.lbl.dsd.sea.nio.util;
007    
008    import org.apache.log4j.ConsoleAppender;
009    import org.apache.log4j.Layout;
010    import org.apache.log4j.Level;
011    import org.apache.log4j.spi.LoggingEvent;
012    
013    /**
014     * Log4J Appender which prints to System.out and shows different log levels in
015     * different colors; very useful for effectively sieving through large number of
016     * log messages. Colors are used only on Unix, and ignored on Windows because we
017     * don't know how to do it. (If it's possible and you know how, submit a
018     * patch!); If you wish to use this appender let log4j know about it by adding
019     * "log4j.appender.CONSOLE=gov.lbl.dsd.sea.nio.util.ColorConsoleAppender" to the
020     * log4j.properties file.
021     * 
022     * @author whoschek@lbl.gov
023     * @author $Author: hoschek3 $
024     * @version $Revision: 1.1 $, $Date: 2004/06/17 18:34:39 $
025     */
026    public class ColorConsoleAppender extends ConsoleAppender {
027    
028            private static final char ESCAPE = 033;
029            private static final String UNESCAPE = "[m";
030            private static final String REVERSE = "[7m";
031    
032            private static final String BLACK = "[30m";
033            private static final String RED = "[31m";
034            private static final String GREEN = "[32m";
035            private static final String YELLOW = "[33m";
036            private static final String BLUE = "[34m";
037            private static final String PURPLE = "[35m";
038            private static final String CYAN = "[36m";
039            private static final String SILVER = "[37m";
040            private static final String WHITE = "[38m";             
041    
042            private static final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
043    
044            // overridden
045            protected void subAppend(LoggingEvent event) {
046                    this.qw.write(formatEvent(event));
047    
048                    if (layout.ignoresThrowable()) {
049                            String[] s = event.getThrowableStrRep();
050                            if (s != null) {
051                                    int len = s.length;
052                                    for (int i = 0; i < len; i++) {
053                                            if (!isWindows) {
054                                                    this.qw.write(toColorString(event.getLevel()).toString());                                              
055                                            }
056                                            this.qw.write(s[i]);
057                                            if (!isWindows) {
058                                                    this.qw.write(ESCAPE + UNESCAPE);                                               
059                                            }
060                                            this.qw.write(Layout.LINE_SEP);
061                                    }
062                            }
063                    }
064    
065                    if (this.immediateFlush) {
066                            this.qw.flush();
067                    }
068            }
069    
070            protected String formatEvent(LoggingEvent event) {
071    
072                    String toPrint = this.layout.format(event);
073                    if (isWindows) {
074                            return toPrint;
075                    } 
076                    else {
077                            StringBuffer s = this.toColorString(event.getLevel());
078                            
079                            //remove newline
080                            s.append(toPrint.substring(0, toPrint.length() - 1));
081    
082                            // reset colors
083                            s.append(ESCAPE).append(UNESCAPE);
084                            
085                            s.append(Layout.LINE_SEP);
086                            return s.toString();
087                    }
088    
089            }
090    
091            protected StringBuffer toColorString(Level level) {
092                    StringBuffer s = new StringBuffer(2);
093                    s.append(ESCAPE);
094                    
095                    switch (level.toInt()) {
096                            case Level.ERROR_INT:
097                                    s.append(RED);
098                                    break;
099                            case Level.WARN_INT:
100                                    s.append(PURPLE);
101                                    break;
102                            case Level.INFO_INT:
103                                    s.append(GREEN);
104                                    break;
105                            case Level.FATAL_INT:
106                                    s.append(RED).append(ESCAPE).append(REVERSE);
107                                    break;
108                            case Level.DEBUG_INT:
109                                    s.append(BLUE);
110                                    break;
111                            default:
112                                    s.append(CYAN);
113                                    break;
114                    }
115                    return s;
116            }
117    }