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 }