KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > common > util > LoggingOutputStream


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: sequoia@continuent.org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Initial developer(s): Jim Moore
20  * Contributor(s): Nicolas Modrzyk
21  */

22
23 package org.continuent.sequoia.common.util;
24
25 import java.io.IOException JavaDoc;
26 import java.io.OutputStream JavaDoc;
27
28 import org.apache.log4j.Category;
29 import org.apache.log4j.Priority;
30
31 /**
32  * An OutputStream that flushes out to a Category.
33  * <p>
34  * Note that no data is written out to the Category until the stream is flushed
35  * or closed.
36  * <p>
37  *
38  * @author <a HREF="mailto://Jim.Moore@rocketmail.com">Jim Moore</a>
39  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk</a>
40  *
41  * @see Category
42  */

43 public class LoggingOutputStream extends OutputStream JavaDoc
44 {
45   protected static final String JavaDoc LINE_SEPARATOR = System
46                                                           .getProperty("line.separator");
47   /**
48    * Used to maintain the contract of {@link #close()}.
49    */

50   protected boolean hasBeenClosed = false;
51   /**
52    * The internal buffer where data is stored.
53    */

54   protected byte[] buf;
55   /**
56    * The number of valid bytes in the buffer. This value is always in the range
57    * <tt>0</tt> through <tt>buf.length</tt>; elements <tt>buf[0]</tt>
58    * through <tt>buf[count-1]</tt> contain valid byte data.
59    */

60   protected int count;
61   /**
62    * Remembers the size of the buffer for speed.
63    */

64   private int bufLength;
65   /**
66    * The default number of bytes in the buffer. =2048
67    */

68   public static final int DEFAULT_BUFFER_LENGTH = 2048;
69   /**
70    * The category to write to.
71    */

72   protected Category category;
73   /**
74    * The priority to use when writing to the Category.
75    */

76   protected Priority priority;
77
78   private LoggingOutputStream()
79   {
80     // illegal
81
}
82
83   /**
84    * Creates the LoggingOutputStream to flush to the given Category.
85    *
86    * @param cat the Category to write to
87    * @param priority the Priority to use when writing to the Category
88    * @exception IllegalArgumentException if cat == null or priority == null
89    */

90   public LoggingOutputStream(Category cat, Priority priority)
91       throws IllegalArgumentException JavaDoc
92   {
93     if (cat == null)
94     {
95       throw new IllegalArgumentException JavaDoc("cat == null");
96     }
97     if (priority == null)
98     {
99       throw new IllegalArgumentException JavaDoc("priority == null");
100     }
101     this.priority = priority;
102     category = cat;
103     bufLength = DEFAULT_BUFFER_LENGTH;
104     buf = new byte[DEFAULT_BUFFER_LENGTH];
105     count = 0;
106   }
107
108   /**
109    * Closes this output stream and releases any system resources associated
110    * with this stream. The general contract of <code>close</code> is that it
111    * closes the output stream. A closed stream cannot perform output operations
112    * and cannot be reopened.
113    */

114   public void close()
115   {
116     flush();
117     hasBeenClosed = true;
118   }
119
120   /**
121    * Writes the specified byte to this output stream. The general contract for
122    * <code>write</code> is that one byte is written to the output stream. The
123    * byte to be written is the eight low-order bits of the argument <code>b</code>.
124    * The 24 high-order bits of <code>b</code> are ignored.
125    *
126    * @param b the <code>byte</code> to write
127    * @exception IOException if an I/O error occurs. In particular, an <code>IOException</code>
128    * may be thrown if the output stream has been closed.
129    */

130   public void write(final int b) throws IOException JavaDoc
131   {
132     if (hasBeenClosed)
133     {
134       throw new IOException JavaDoc("The stream has been closed.");
135     }
136     // don't log nulls
137
if (b == 0)
138     {
139       return;
140     }
141     // would this be writing past the buffer?
142
if (count == bufLength)
143     {
144       // grow the buffer
145
final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
146       final byte[] newBuf = new byte[newBufLength];
147       System.arraycopy(buf, 0, newBuf, 0, bufLength);
148       buf = newBuf;
149       bufLength = newBufLength;
150     }
151     buf[count] = (byte) b;
152     count++;
153   }
154
155   /**
156    * Flushes this output stream and forces any buffered output bytes to be
157    * written out. The general contract of <code>flush</code> is that calling
158    * it is an indication that, if any bytes previously written have been
159    * buffered by the implementation of the output stream, such bytes should
160    * immediately be written to their intended destination.
161    */

162   public void flush()
163   {
164     if (count == 0)
165     {
166       return;
167     }
168     // don't print out blank lines; flushing from PrintStream puts out these
169
if (count == LINE_SEPARATOR.length())
170     {
171       if (((char) buf[0]) == LINE_SEPARATOR.charAt(0) && ((count == 1) || // <-
172
// Unix
173
// &
174
// Mac,
175
// ->
176
// Windows
177
((count == 2) && ((char) buf[1]) == LINE_SEPARATOR.charAt(1))))
178       {
179         reset();
180         return;
181       }
182     }
183     final byte[] theBytes = new byte[count];
184     System.arraycopy(buf, 0, theBytes, 0, count);
185     
186     // ADDED: We don't want blank lines at all
187
String JavaDoc bytes = new String JavaDoc(theBytes).trim();
188     int line = -1;
189     while((line = bytes.indexOf(LINE_SEPARATOR))!=-1)
190     {
191         bytes = bytes.substring(0, line) + bytes.substring(line+LINE_SEPARATOR.length());
192     }
193     // END ADDED
194

195     category.log(priority, bytes);
196     reset();
197   }
198
199   private void reset()
200   {
201     // not resetting the buffer -- assuming that if it grew that it
202
// will likely grow similarly again
203
count = 0;
204   }
205 }
Popular Tags