Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

LoggingOutputStream.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Jim Moore
00022  * Contributor(s): Nicolas Modrzyk
00023  */
00024 
00025 package org.objectweb.cjdbc.common.util;
00026 
00027 import java.io.IOException;
00028 import java.io.OutputStream;
00029 
00030 import org.apache.log4j.Category;
00031 import org.apache.log4j.Priority;
00032 
00033 /**
00034  * An OutputStream that flushes out to a Category.
00035  * <p>
00036  * Note that no data is written out to the Category until the stream is flushed
00037  * or closed.
00038  * <p>
00039  * 
00040  * @author <a href="mailto://Jim.Moore@rocketmail.com">Jim Moore</a>
00041  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk</a>
00042  * 
00043  * @see Category
00044  */
00045 public class LoggingOutputStream extends OutputStream
00046 {
00047   protected static final String LINE_SEPERATOR        = System
00048                                                           .getProperty("line.separator");
00049   /**
00050    * Used to maintain the contract of {@link #close()}.
00051    */
00052   protected boolean             hasBeenClosed         = false;
00053   /**
00054    * The internal buffer where data is stored.
00055    */
00056   protected byte[]              buf;
00057   /**
00058    * The number of valid bytes in the buffer. This value is always in the range
00059    * <tt>0</tt> through <tt>buf.length</tt>; elements <tt>buf[0]</tt>
00060    * through <tt>buf[count-1]</tt> contain valid byte data.
00061    */
00062   protected int                 count;
00063   /**
00064    * Remembers the size of the buffer for speed.
00065    */
00066   private int                   bufLength;
00067   /**
00068    * The default number of bytes in the buffer. =2048
00069    */
00070   public static final int       DEFAULT_BUFFER_LENGTH = 2048;
00071   /**
00072    * The category to write to.
00073    */
00074   protected Category            category;
00075   /**
00076    * The priority to use when writing to the Category.
00077    */
00078   protected Priority            priority;
00079 
00080   private LoggingOutputStream()
00081   {
00082     // illegal
00083   }
00084 
00085   /**
00086    * Creates the LoggingOutputStream to flush to the given Category.
00087    * 
00088    * @param cat the Category to write to
00089    * @param priority the Priority to use when writing to the Category
00090    * @exception IllegalArgumentException if cat == null or priority == null
00091    */
00092   public LoggingOutputStream(Category cat, Priority priority)
00093       throws IllegalArgumentException
00094   {
00095     if (cat == null)
00096     {
00097       throw new IllegalArgumentException("cat == null");
00098     }
00099     if (priority == null)
00100     {
00101       throw new IllegalArgumentException("priority == null");
00102     }
00103     this.priority = priority;
00104     category = cat;
00105     bufLength = DEFAULT_BUFFER_LENGTH;
00106     buf = new byte[DEFAULT_BUFFER_LENGTH];
00107     count = 0;
00108   }
00109 
00110   /**
00111    * Closes this output stream and releases any system resources associated
00112    * with this stream. The general contract of <code>close</code> is that it
00113    * closes the output stream. A closed stream cannot perform output operations
00114    * and cannot be reopened.
00115    */
00116   public void close()
00117   {
00118     flush();
00119     hasBeenClosed = true;
00120   }
00121 
00122   /**
00123    * Writes the specified byte to this output stream. The general contract for
00124    * <code>write</code> is that one byte is written to the output stream. The
00125    * byte to be written is the eight low-order bits of the argument <code>b</code>.
00126    * The 24 high-order bits of <code>b</code> are ignored.
00127    * 
00128    * @param b the <code>byte</code> to write
00129    * @exception IOException if an I/O error occurs. In particular, an <code>IOException</code>
00130    *                         may be thrown if the output stream has been closed.
00131    */
00132   public void write(final int b) throws IOException
00133   {
00134     if (hasBeenClosed)
00135     {
00136       throw new IOException("The stream has been closed.");
00137     }
00138     // don't log nulls
00139     if (b == 0)
00140     {
00141       return;
00142     }
00143     // would this be writing past the buffer?
00144     if (count == bufLength)
00145     {
00146       // grow the buffer
00147       final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
00148       final byte[] newBuf = new byte[newBufLength];
00149       System.arraycopy(buf, 0, newBuf, 0, bufLength);
00150       buf = newBuf;
00151       bufLength = newBufLength;
00152     }
00153     buf[count] = (byte) b;
00154     count++;
00155   }
00156 
00157   /**
00158    * Flushes this output stream and forces any buffered output bytes to be
00159    * written out. The general contract of <code>flush</code> is that calling
00160    * it is an indication that, if any bytes previously written have been
00161    * buffered by the implementation of the output stream, such bytes should
00162    * immediately be written to their intended destination.
00163    */
00164   public void flush()
00165   {
00166     if (count == 0)
00167     {
00168       return;
00169     }
00170     // don't print out blank lines; flushing from PrintStream puts out these
00171     if (count == LINE_SEPERATOR.length())
00172     {
00173       if (((char) buf[0]) == LINE_SEPERATOR.charAt(0) && ((count == 1) || // <-
00174                                                                                                                                  // Unix
00175                                                                                                                                  // &
00176                                                                                                                                  // Mac,
00177                                                                                                                                  // ->
00178                                                                                                                                  // Windows
00179           ((count == 2) && ((char) buf[1]) == LINE_SEPERATOR.charAt(1))))
00180       {
00181         reset();
00182         return;
00183       }
00184     }
00185     final byte[] theBytes = new byte[count];
00186     System.arraycopy(buf, 0, theBytes, 0, count);
00187     
00188     // ADDED: We don't want blank lines at all
00189     String bytes  = new String(theBytes).trim();
00190     int line = -1;
00191     while((line = bytes.indexOf(LINE_SEPERATOR))!=-1)
00192     {
00193         bytes = bytes.substring(0, line) + bytes.substring(line+LINE_SEPERATOR.length());
00194     }
00195     // END ADDED 
00196     
00197     category.log(priority, bytes);
00198     reset();
00199   }
00200 
00201   private void reset()
00202   {
00203     // not resetting the buffer -- assuming that if it grew that it
00204     //   will likely grow similarly again
00205     count = 0;
00206   }
00207 }

Generated on Mon Apr 11 22:01:32 2005 for C-JDBC by  doxygen 1.3.9.1