001 /*
002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.11/src/java/org/apache/commons/ssl/LogWrapper.java $
003 * $Revision: 121 $
004 * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
005 *
006 * ====================================================================
007 * Licensed to the Apache Software Foundation (ASF) under one
008 * or more contributor license agreements. See the NOTICE file
009 * distributed with this work for additional information
010 * regarding copyright ownership. The ASF licenses this file
011 * to you under the Apache License, Version 2.0 (the
012 * "License"); you may not use this file except in compliance
013 * with the License. You may obtain a copy of the License at
014 *
015 * http://www.apache.org/licenses/LICENSE-2.0
016 *
017 * Unless required by applicable law or agreed to in writing,
018 * software distributed under the License is distributed on an
019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020 * KIND, either express or implied. See the License for the
021 * specific language governing permissions and limitations
022 * under the License.
023 * ====================================================================
024 *
025 * This software consists of voluntary contributions made by many
026 * individuals on behalf of the Apache Software Foundation. For more
027 * information on the Apache Software Foundation, please see
028 * <http://www.apache.org/>.
029 *
030 */
031
032 package org.apache.commons.ssl;
033
034 import java.io.BufferedOutputStream;
035 import java.io.FileOutputStream;
036 import java.io.IOException;
037 import java.io.OutputStream;
038 import java.io.PrintStream;
039 import java.text.DateFormat;
040 import java.text.SimpleDateFormat;
041 import java.util.Date;
042
043 /**
044 * <p/>
045 * LogWrapper can be used for situations where log4j might not be available on
046 * the classpath. It presents the most basic and critical components of the
047 * log4j API, and passes all log calls through to log4j if possible. If log4j
048 * is not available, logging is sent to standard-out by default.
049 * <p/>
050 * This default logging to standard-out (which only occurs if log4j is NOT
051 * available) can be disabled or changed via the static setBackupStream() and
052 * setBackupLogFile() methods.
053 *
054 * @author Credit Union Central of British Columbia
055 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
056 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
057 * @since 3-Aug-2006
058 */
059 public class LogWrapper {
060
061 // final static String[] LEVELS = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
062 final static String[] LEVELS = {"+", " ", "!", "*", "#"};
063 final static String TIMESTAMP_PATTERN = "zzz:yyyy-MM-dd/HH:mm:ss.SSS";
064 final static int TIMESTAMP_LENGTH = TIMESTAMP_PATTERN.length();
065 final static String LINE_SEPARATOR = System.getProperty("line.separator");
066 final static DateFormat DF = new SimpleDateFormat(TIMESTAMP_PATTERN);
067
068 private final static LogWrapper NOOP = new LogWrapper();
069
070 /** Should we print DEBUG statements if log4j is not available? */
071 private final static boolean DEBUG = true;
072
073 /** true if log4j is available */
074 public final static boolean log4j;
075
076 /**
077 * OutputStream to log to if log4j is not available. Set it to null to
078 * disable.
079 */
080 private static volatile OutputStream backup = System.out;
081
082 /** The wrappingPrintStream is lazy-initted if we have to log a stacktrace. */
083 private static volatile PrintStream wrappingPrintStream = null;
084
085 private final LogHelper h;
086
087 static {
088 boolean avail = false;
089 try {
090 // LogHelper's constructor will blow up if log4j.jar isn't on the
091 // classpath.
092 LogHelper lh = new LogHelper(LogWrapper.class);
093 lh.hashCode();
094 avail = true;
095 }
096 catch (Throwable t) {
097 avail = false;
098 }
099 finally {
100 log4j = avail;
101 }
102 }
103
104 public static boolean isLog4jAvailable() { return log4j; }
105
106 public static LogWrapper getLogger(Class c) {
107 return log4j ? new LogWrapper(c) : NOOP;
108 }
109
110 public static LogWrapper getLogger(String s) {
111 return log4j ? new LogWrapper(s) : NOOP;
112 }
113
114 private LogWrapper() { this.h = null; }
115
116 private LogWrapper(Class c) { this.h = new LogHelper(c); }
117
118 private LogWrapper(String s) { this.h = new LogHelper(s); }
119
120 public void debug(Object o) {
121 if (t(0, o, null)) {
122 h.debug(o);
123 }
124 }
125
126 public void debug(Object o, Throwable t) {
127 if (t(0, o, t)) {
128 h.debug(o, t);
129 }
130 }
131
132 public void info(Object o) {
133 if (t(1, o, null)) {
134 h.info(o);
135 }
136 }
137
138 public void info(Object o, Throwable t) {
139 if (t(1, o, t)) {
140 h.info(o, t);
141 }
142 }
143
144 public void warn(Object o) {
145 if (t(2, o, null)) {
146 h.warn(o);
147 }
148 }
149
150 public void warn(Object o, Throwable t) {
151 if (t(2, o, t)) {
152 h.warn(o, t);
153 }
154 }
155
156 public void error(Object o) {
157 if (t(3, o, null)) {
158 h.error(o);
159 }
160 }
161
162 public void error(Object o, Throwable t) {
163 if (t(3, o, t)) {
164 h.error(o, t);
165 }
166 }
167
168 public void fatal(Object o) {
169 if (t(4, o, null)) {
170 h.fatal(o);
171 }
172 }
173
174 public void fatal(Object o, Throwable t) {
175 if (t(4, o, t)) {
176 h.fatal(o, t);
177 }
178 }
179
180 public boolean isDebugEnabled() { return log4j ? h.isDebugEnabled() : DEBUG;}
181
182 public boolean isInfoEnabled() { return !log4j || h.isInfoEnabled(); }
183
184 public Object getLog4jLogger() { return log4j ? h.getLog4jLogger() : null; }
185
186
187 /**
188 * Tests if log4j is available. If not, logs to backup OutputStream (if
189 * backup != null).
190 *
191 * @param level log4j logging level for this statement
192 * @param o object to log
193 * @param t throwable to log
194 * @return true if log4j is available, false if log4j is not. If it returns
195 * false, as a side-effect, it will also log the statement.
196 */
197 private boolean t(int level, Object o, Throwable t) {
198 if (log4j) {
199 return true;
200 } else {
201 // LogWrapper doesn't log debug statements if Log4j is not available
202 // and DEBUG is false.
203 if (backup != null && (DEBUG || level > 0)) {
204 String s = ""; // log4j allows null
205 if (o != null) {
206 try {
207 s = (String) o;
208 }
209 catch (ClassCastException cce) {
210 s = o.toString();
211 }
212 }
213 int len = s.length() + TIMESTAMP_LENGTH + 9;
214 String timestamp = DF.format(new Date());
215 StringBuffer buf = new StringBuffer(len);
216 buf.append(timestamp);
217 if (LEVELS[level].length() == 1) {
218 buf.append(LEVELS[level]);
219 } else {
220 buf.append(' ');
221 buf.append(LEVELS[level]);
222 buf.append(' ');
223 }
224 buf.append(s);
225 buf.append(LINE_SEPARATOR);
226 s = buf.toString();
227 byte[] logBytes = s.getBytes();
228 try {
229 if (t == null) {
230 backup.write(logBytes);
231 } else {
232 synchronized (backup) {
233 backup.write(logBytes);
234 if (t != null) {
235 if (wrappingPrintStream == null) {
236 wrappingPrintStream = new PrintStream(backup, false);
237 }
238 t.printStackTrace(wrappingPrintStream);
239 wrappingPrintStream.flush();
240 }
241 }
242 }
243 backup.flush(); // J2RE 1.5.0 IBM J9 2.3 Linux x86-32 needs this.
244 }
245 catch (IOException ioe) {
246 throw new RuntimeException(ioe.toString());
247 }
248 }
249 return false;
250 }
251 }
252
253 /**
254 * Set file to log to if log4j is not available.
255 *
256 * @param f path to use for backup log file (if log4j not available)
257 * @throws IOException if we can't write to the given path
258 */
259 public static void setBackupLogFile(String f)
260 throws IOException {
261 if (!log4j) {
262 OutputStream out = new FileOutputStream(f, true);
263 out = new BufferedOutputStream(out);
264 setBackupStream(out);
265 }
266 }
267
268 /**
269 * Set PrintStream to log to if log4j is not available. Set to null to
270 * disable. Default value is System.out.
271 *
272 * @param os outputstream to use for backup logging (if log4j not available)
273 */
274 public static void setBackupStream(OutputStream os) {
275 // synchronize on the old backup - don't want to pull the rug out from
276 // under him if he's working on a big stacktrace or something like that.
277 if (backup != null) {
278 synchronized (backup) {
279 wrappingPrintStream = null;
280 backup = os;
281 }
282 } else {
283 wrappingPrintStream = null;
284 backup = os;
285 }
286 }
287
288 /**
289 * Get the PrintStream we're logging to if log4j is not available.
290 *
291 * @return OutputStream we're using as our log4j replacement.
292 */
293 public static OutputStream getBackupStream() { return backup; }
294
295 }