From: <do...@hy...> - 2008-01-15 07:05:07
|
Author: dougm Date: 2008-01-14 23:05:05 -0800 (Mon, 14 Jan 2008) New Revision: 7544 URL: http://svn.hyperic.org/?view=rev&root=Hyperic+HQ&revision=7544 Added: trunk/src/org/hyperic/hq/agent/server/LoggingOutputStream.java Log: [HHQ-1162] For System.{out,err}->log4j (http://svn.apache.org/viewvc/logging/log4j/tags/v1_2_15/contribs/JimMoore/LoggingOutputStream.java) Added: trunk/src/org/hyperic/hq/agent/server/LoggingOutputStream.java =================================================================== --- trunk/src/org/hyperic/hq/agent/server/LoggingOutputStream.java (rev 0) +++ trunk/src/org/hyperic/hq/agent/server/LoggingOutputStream.java 2008-01-15 07:05:05 UTC (rev 7544) @@ -0,0 +1,212 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//copyof: log4j/tags/v1_2_15/contribs/JimMoore/LoggingOutputStream.java +package org.hyperic.hq.agent.server; //XXX .util ? + +import java.io.*; +import org.apache.log4j.*; + + +/** + * An OutputStream that flushes out to a Category.<p> + * + * Note that no data is written out to the Category until the stream is + * flushed or closed.<p> + * + * Example:<pre> + * // make sure everything sent to System.err is logged + * System.setErr(new PrintStream(new LoggingOutputStream(Category.getRoot(), Priority.WARN), true)); + * + * // make sure everything sent to System.out is also logged + * System.setOut(new PrintStream(new LoggingOutputStream(Category.getRoot(), Priority.INFO), true)); + * </pre> + * + * @author <a href="mailto://Jim...@ro...">Jim Moore</a> + * @see Category + */ +public class LoggingOutputStream extends OutputStream { + protected static final String LINE_SEPERATOR = System.getProperty("line.separator"); + + + /** + * Used to maintain the contract of {@link #close()}. + */ + protected boolean hasBeenClosed = false; + + /** + * The internal buffer where data is stored. + */ + protected byte[] buf; + + /** + * The number of valid bytes in the buffer. This value is always + * in the range <tt>0</tt> through <tt>buf.length</tt>; elements + * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid + * byte data. + */ + protected int count; + + + /** + * Remembers the size of the buffer for speed. + */ + private int bufLength; + + /** + * The default number of bytes in the buffer. =2048 + */ + public static final int DEFAULT_BUFFER_LENGTH = 2048; + + + /** + * The category to write to. + */ + protected Category category; + + /** + * The priority to use when writing to the Category. + */ + protected Priority priority; + + + private LoggingOutputStream() { + // illegal + } + + + /** + * Creates the LoggingOutputStream to flush to the given Category. + * + * @param cat the Category to write to + * + * @param priority the Priority to use when writing to the Category + * + * @exception IllegalArgumentException + * if cat == null or priority == null + */ + public LoggingOutputStream(Category cat, Priority priority) + throws IllegalArgumentException { + if (cat == null) { + throw new IllegalArgumentException("cat == null"); + } + if (priority == null) { + throw new IllegalArgumentException("priority == null"); + } + + this.priority = priority; + category = cat; + bufLength = DEFAULT_BUFFER_LENGTH; + buf = new byte[DEFAULT_BUFFER_LENGTH]; + count = 0; + } + + + /** + * Closes this output stream and releases any system resources + * associated with this stream. The general contract of <code>close</code> + * is that it closes the output stream. A closed stream cannot perform + * output operations and cannot be reopened. + */ + public void close() { + flush(); + hasBeenClosed = true; + } + + + /** + * Writes the specified byte to this output stream. The general + * contract for <code>write</code> is that one byte is written + * to the output stream. The byte to be written is the eight + * low-order bits of the argument <code>b</code>. The 24 + * high-order bits of <code>b</code> are ignored. + * + * @param b the <code>byte</code> to write + * + * @exception IOException + * if an I/O error occurs. In particular, + * an <code>IOException</code> may be thrown if the + * output stream has been closed. + */ + public void write(final int b) throws IOException { + if (hasBeenClosed) { + throw new IOException("The stream has been closed."); + } + + // don't log nulls + if (b == 0) { + return; + } + + // would this be writing past the buffer? + if (count == bufLength) { + // grow the buffer + final int newBufLength = bufLength+DEFAULT_BUFFER_LENGTH; + final byte[] newBuf = new byte[newBufLength]; + + System.arraycopy(buf, 0, newBuf, 0, bufLength); + + buf = newBuf; + bufLength = newBufLength; + } + + buf[count] = (byte)b; + count++; + } + + + /** + * Flushes this output stream and forces any buffered output bytes + * to be written out. The general contract of <code>flush</code> is + * that calling it is an indication that, if any bytes previously + * written have been buffered by the implementation of the output + * stream, such bytes should immediately be written to their + * intended destination. + */ + public void flush() { + if (count == 0) { + return; + } + + // don't print out blank lines; flushing from PrintStream puts out these + if (count == LINE_SEPERATOR.length()) { + if ( ((char)buf[0]) == LINE_SEPERATOR.charAt(0) && + ( ( count == 1 ) || // <- Unix & Mac, -> Windows + ( (count == 2) && ((char)buf[1]) == LINE_SEPERATOR.charAt(1) ) ) ) { + reset(); + return; + } + } + + final byte[] theBytes = new byte[count]; + + System.arraycopy(buf, 0, theBytes, 0, count); + + category.log(priority, new String(theBytes)); + + reset(); + } + + + private void reset() { + // not resetting the buffer -- assuming that if it grew that it + // will likely grow similarly again + count = 0; + } + +} + |