/* * @(#)Log.java 0.3-3 06/05/2001 * * This file is part of the HTTPClient package * Copyright (C) 1996-2001 Ronald Tschalär * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA * * For questions, suggestions, bug-reports, enhancement-requests etc. * I may be contacted at: * * ronald@innovation.ch * * The HTTPClient's home page is located at: * * http://www.innovation.ch/java/HTTPClient/ * */ package HTTPClient; import java.io.IOException; import java.io.Writer; import java.io.FileWriter; import java.io.PrintWriter; import java.io.OutputStreamWriter; import java.io.ByteArrayOutputStream; import java.util.Calendar; import java.util.TimeZone; /** * This is a simple logger for the HTTPClient. It defines a number of * "facilities", each representing one or more logically connected classes. * Logging can be enabled or disabled on a per facility basis. Furthermore, the * logging output can be redirected to any desired place, such as a file or a * buffer; by default all logging goes to System.err. * *

All log entries are preceded by the name of the currently executing * thread, enclosed in {}'s, and the current time in hours, minutes, seconds, * and milliseconds, enclosed in []'s. Example: * {Thread-5} [20:14:03.244] Conn: Sending Request * *

When the class is loaded, two java system properties are read: * HTTPClient.log.file and HTTPClient.log.mask. The first * one, if set, causes all logging to be redirected to the file with the given * name. The second one, if set, is used for setting which facilities are * enabled; the value must be the bitwise OR ('|') of the values of the desired * enabled facilities. E.g. a value of 3 would enable logging for the * HTTPConnection and HTTPResponse, a value of 16 would enable cookie related * logging, and a value of 8 would enable authorization related logging; a * value of -1 would enable logging for all facilities. By default logging is * disabled. * * @version 0.3-3 06/05/2001 * @author Ronald Tschalär * @since V0.3-3 */ public class Log { /** The HTTPConnection facility (1) */ public static final int CONN = 1 << 0; /** The HTTPResponse facility (2) */ public static final int RESP = 1 << 1; /** The StreamDemultiplexor facility (4) */ public static final int DEMUX = 1 << 2; /** The Authorization facility (8) */ public static final int AUTH = 1 << 3; /** The Cookies facility (16) */ public static final int COOKI = 1 << 4; /** The Modules facility (32) */ public static final int MODS = 1 << 5; /** The Socks facility (64) */ public static final int SOCKS = 1 << 6; /** The ULRConnection facility (128) */ public static final int URLC = 1 << 7; /** All the facilities - for use in setLogging (-1) */ public static final int ALL = ~0; private static final String NL = System.getProperty("line.separator"); private static final long TZ_OFF; private static int facMask = 0; private static Writer logWriter = new OutputStreamWriter(System.err); private static boolean closeWriter = false; static { Calendar now = Calendar.getInstance(); TZ_OFF = TimeZone.getDefault().getOffset(now.get(Calendar.ERA), now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.DAY_OF_WEEK), now.get(Calendar.MILLISECOND)); try { String file = System.getProperty("HTTPClient.log.file"); if (file != null) { try { setLogWriter(new FileWriter(file), true); } catch (IOException ioe) { System.err.println("failed to open file log stream `" + file + "': " + ioe); } } } catch (Exception e) { } try { facMask = Integer.getInteger("HTTPClient.log.mask", 0).intValue(); } catch (Exception e) { } } // Constructors /** * Not meant to be instantiated */ private Log() { } // Methods /** * Write the given message to the current log if logging for the given facility is * enabled. * * @param facility the facility which is logging the message * @param msg the message to log */ public static void write(int facility, String msg) { if ((facMask & facility) == 0) return; try { writePrefix(); logWriter.write(msg); logWriter.write(NL); logWriter.flush(); } catch (IOException ioe) { System.err.println("Failed to write to log: " + ioe); System.err.println("Failed log Entry was: " + msg); } } /** * Write the stack trace of the given exception to the current log if logging for the * given facility is enabled. * * @param facility the facility which is logging the message * @param prefix the string with which to prefix the stack trace; may be null * @param t the exception to log */ public static void write(int facility, String prefix, Throwable t) { if ((facMask & facility) == 0) return; synchronized (Log.class) { if (!(logWriter instanceof PrintWriter)) logWriter = new PrintWriter(logWriter); } try { writePrefix(); if (prefix != null) logWriter.write(prefix); t.printStackTrace((PrintWriter) logWriter); logWriter.flush(); } catch (IOException ioe) { System.err.println("Failed to write to log: " + ioe); System.err.print("Failed log Entry was: " + prefix); t.printStackTrace(System.err); } } /** * Write the contents of the given buffer to the current log if logging for * the given facility is enabled. * * @param facility the facility which is logging the message * @param prefix the string with which to prefix the buffer contents; * may be null * @param buf the buffer to dump */ public static void write(int facility, String prefix, ByteArrayOutputStream buf) { if ((facMask & facility) == 0) return; try { writePrefix(); if (prefix != null) logWriter.write(prefix); logWriter.write(NL); logWriter.write(new String(buf.toByteArray(), "ISO_8859-1")); logWriter.flush(); } catch (IOException ioe) { System.err.println("Failed to write to log: " + ioe); System.err.println("Failed log Entry was: " + prefix); System.err.println(new String(buf.toByteArray())); } } /** * Write a log line prefix of the form *

     *  {thread-name} [time]
     * 
*/ private static final void writePrefix() throws IOException { logWriter.write("{" + Thread.currentThread().getName() + "} "); int mill = (int) ((System.currentTimeMillis() + TZ_OFF) % (24 * 3600000)); int secs = mill / 1000; int mins = secs / 60; int hours = mins / 60; logWriter.write("[" + fill2(hours) + ':' + fill2(mins - hours*60) + ':' + fill2(secs - mins * 60) + '.' + fill3(mill - secs * 1000) + "] "); } private static final String fill2(int num) { return ((num < 10) ? "0" : "") + num; } private static final String fill3(int num) { return ((num < 10) ? "00" : (num < 100) ? "0" : "") + num; } /** * Check whether logging for the given facility is enabled or not. * * @param facility the facility to check * @return true if logging for the given facility is enable; false otherwise */ public static boolean isEnabled(int facility) { return ((facMask & facility) != 0); } /** * Enable or disable logging for the given facilities. * * @param facilities the facilities for which to enable or disable logging. * This is bitwise OR ('|') of all the desired * facilities; use {@link #ALL ALL} to affect all facilities * @param enable if true, enable logging for the chosen facilities; if * false, disable logging for them. */ public static void setLogging(int facilities, boolean enable) { if (enable) facMask |= facilities; else facMask &= ~facilities; } /** * Set the writer to which to log. By default, things are logged to * System.err. * * @param log the writer to log to; if null, nothing is changed * @param closeWhenDone if true, close this stream when a new stream is set * again */ public static void setLogWriter(Writer log, boolean closeWhenDone) { if (log == null) return; if (closeWriter) { try { logWriter.close(); } catch (IOException ioe) { System.err.println("Error closing log stream: " + ioe); } } logWriter = log; closeWriter = closeWhenDone; } }