1 import java.io.BufferedOutputStream;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.PrintStream;
6 import java.text.DateFormat;
7 import java.text.SimpleDateFormat;
8 import java.util.Date;
9
10 /**
11 * <p>
12 * LogWrapper can be used for situations where log4j might not be available on
13 * the classpath. It presents the most basic and critical components of the
14 * log4j API, and passes all log calls through to log4j if possible. If log4j
15 * is not available, logging is sent to standard-out by default.
16 * <p>
17 * This default logging to standard-out (which only occurs if log4j is NOT
18 * available) can be disabled or changed via the static setBackupStream() and
19 * setBackupLogFile() methods.
20 *
21 * @author Credit Union Central of British Columbia
22 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
23 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
24 * @since 3-Aug-2006
25 */
26 public class LogWrapper {
27
28 final static String[] LEVELS = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
29 final static String TIMESTAMP_PATTERN = "zzz:yyyy-MM-dd/HH:mm:ss.SSS";
30 final static int TIMESTAMP_LENGTH = TIMESTAMP_PATTERN.length();
31 final static String LINE_SEPARATOR = System.getProperty( "line.separator" );
32 final static DateFormat DF = new SimpleDateFormat(TIMESTAMP_PATTERN);
33
34 private final static LogWrapper NOOP = new LogWrapper();
35
36 /**
37 * true if log4j is available
38 */
39 public final static boolean log4j;
40
41 /**
42 * OutputStream to log to if log4j is not available. Set it to null to
43 * disable.
44 */
45 private static volatile OutputStream backup = System.out;
46
47 /**
48 * The wrappingPrintStream is lazy-initted if we have to log a stacktrace.
49 */
50 private static volatile PrintStream wrappingPrintStream = null;
51
52 private final LogHelper h;
53
54 static {
55 boolean avail = false;
56 try {
57 // LogHelper's constructor will blow up if log4j.jar isn't on the
58 // classpath.
59 LogHelper lh = new LogHelper( LogWrapper.class );
60 lh.hashCode();
61 avail = true;
62 }
63 catch (Throwable t) {}
64 finally {
65 log4j = avail;
66 }
67 }
68
69 public static boolean isLog4jAvailable() { return log4j; }
70
71 public static LogWrapper getLogger( Class c ) {
72 return log4j ? new LogWrapper( c ) : NOOP;
73 }
74
75 public static LogWrapper getLogger( String s ) {
76 return log4j ? new LogWrapper( s ) : NOOP;
77 }
78
79 private LogWrapper() { this.h = null; }
80 private LogWrapper( Class c ) { this.h = new LogHelper( c ); }
81 private LogWrapper( String s ) { this.h = new LogHelper( s ); }
82 public void debug(Object o) { if (t(0,o,null)) h.debug(o); }
83 public void debug(Object o, Throwable t) { if (t(0,o,t)) h.debug(o,t); }
84 public void info (Object o) { if (t(1,o,null)) h.info(o); }
85 public void info (Object o, Throwable t) { if (t(1,o,t)) h.info(o,t); }
86 public void warn (Object o) { if (t(2,o,null)) h.warn(o); }
87 public void warn (Object o, Throwable t) { if (t(2,o,t)) h.warn(o,t); }
88 public void error(Object o) { if (t(3,o,null)) h.error(o); }
89 public void error(Object o, Throwable t) { if (t(3,o,t)) h.error(o,t); }
90 public void fatal(Object o) { if (t(4,o,null)) h.fatal(o); }
91 public void fatal(Object o, Throwable t) { if (t(4,o,t)) h.fatal(o,t); }
92 public boolean isDebugEnabled() { return log4j ? h.isDebugEnabled() : false;}
93 public boolean isInfoEnabled() { return log4j ? h.isInfoEnabled() : true; }
94 public Object getLog4jLogger() { return log4j ? h.getLog4jLogger() : null; }
95
96
97 /**
98 * Tests if log4j is available. If not, logs to backup OutputStream (if
99 * backup != null).
100 */
101 private final boolean t(int level, Object o, Throwable t) {
102 if ( log4j ) {
103 return true;
104 } else {
105 if ( backup != null ) {
106 String s = ""; // log4j allows null
107 if ( o != null ) {
108 try {
109 s = (String) o;
110 } catch ( ClassCastException cce ) {
111 s = o.toString();
112 }
113 }
114 int len = s.length() + TIMESTAMP_LENGTH + 9;
115 String timestamp = DF.format( new Date() );
116 StringBuffer buf = new StringBuffer( len );
117 buf.append( timestamp );
118 buf.append( ' ' );
119 buf.append( LEVELS[ level ] );
120 buf.append( ' ' );
121 buf.append( s );
122 buf.append( LINE_SEPARATOR );
123 s = buf.toString();
124 byte[] logBytes = s.getBytes();
125 try {
126 if ( t == null ) {
127 backup.write( logBytes );
128 } else {
129 synchronized( backup ) {
130 backup.write( logBytes );
131 if ( t != null ) {
132 if ( wrappingPrintStream == null ) {
133 wrappingPrintStream = new PrintStream( backup, false );
134 }
135 t.printStackTrace( wrappingPrintStream );
136 wrappingPrintStream.flush();
137 }
138 }
139 }
140 backup.flush(); // J2RE 1.5.0 IBM J9 2.3 Linux x86-32 needs this.
141 } catch ( IOException ioe ) {
142 throw new RuntimeException( ioe.toString() );
143 }
144 }
145 return false;
146 }
147 }
148
149 /**
150 * Set file to log to if log4j is not available.
151 * @param f
152 * @throws IOException
153 */
154 public static void setBackupLogFile( String f )
155 throws IOException {
156 if ( !log4j ) {
157 OutputStream out = new FileOutputStream( f, true );
158 out = new BufferedOutputStream( out );
159 setBackupStream( out );
160 }
161 }
162
163 /**
164 * Set PrintStream to log to if log4j is not available. Set to null to
165 * disable. Default value is System.out.
166 *
167 * @param os
168 */
169 public static void setBackupStream( OutputStream os ) {
170 // synchronize on the old backup - don't want to pull the rug out from
171 // under him if he's working on a big stacktrace or something like that.
172 if ( backup != null ) {
173 synchronized( backup ) {
174 wrappingPrintStream = null;
175 backup = os;
176 }
177 }
178 }
179
180 /**
181 * Get the PrintStream we're logging to if log4j is not available.
182 */
183 public static OutputStream getBackupStream() { return backup; }
184
185 }
186