001 package log;
002
003 import java.io.*;
004
005 /**
006 * A stream that can be used to read and process log files.
007 *
008 * <p>The LogInputStream will take an {@link InputStream} and try to interpret the data from that stream as
009 * a log file. You can then obtain the {@link LogEntry LogEntries} in the order they were put into the log
010 * by calling {@link #readEntry}.</p>
011 *
012 * <p><code>LogInputStreams</code> can be filtered in which case you will only see the LogEntries that are
013 * {@link LogEntryFilter#accept accepted} by the {@link LogEntryFilter filter}.</p>
014 *
015 * @author Steffen Zschaler
016 * @version 2.0 14/07/1999
017 * @since v2.0
018 */
019 public class LogInputStream extends Object implements Serializable {
020
021 /**
022 * ID for serialization.
023 */
024 private static final long serialVersionUID = 5413255345890174061L;
025
026 /**
027 * The input stream that backs this stream.
028 */
029 protected InputStream m_isSource;
030
031 /**
032 * The object input stream that is build on top of the input stream. This objects in this stream are
033 * expected to be {@link LogEntry LogEntries}.
034 */
035 protected ObjectInputStream m_oisSource;
036
037 /**
038 * The filter to be applied on the stream, if any.
039 */
040 protected LogEntryFilter m_lefFilter;
041
042 /**
043 * Create a new LogInputStream. There will be no filter.
044 *
045 * @param isSource the InputStream that is the base for this stream.
046 *
047 * @exception IOException if an error occured or the stream is not a valid log file.
048 */
049 public LogInputStream(InputStream isSource) throws IOException {
050 this(isSource, null);
051 }
052
053 /**
054 * Create a new LogInputStream.
055 *
056 * @param isSource the InputStream that is the base for this stream.
057 * @param lef the filter to be applied on the stream.
058 *
059 * @exception IOException if an error occured or the stream is not a valid log file.
060 */
061 public LogInputStream(InputStream isSource, LogEntryFilter lef) throws IOException {
062
063 super();
064
065 m_isSource = isSource;
066
067 // skip the leading zero
068 m_isSource.skip(1);
069
070 m_oisSource = new ObjectInputStream(m_isSource);
071
072 m_lefFilter = lef;
073 }
074
075 /**
076 * Close the stream and all streams that it relies on.
077 *
078 * @exception IOException if there was an error on closing.
079 *
080 * @override Never
081 */
082 public void close() throws IOException {
083 m_oisSource.close();
084 m_isSource.close();
085
086 m_oisSource = null;
087 m_isSource = null;
088 }
089
090 /**
091 * Read the next log entry that is {@link LogEntryFilter#accept accepted} by the filter from the stream.
092 *
093 * @exception IOException if an <code>IOException</code> occurred while reading from the underlying stream.
094 * Especially, this may be an <code>EOFException</code> if the end of the stream has been reached. This is
095 * the only way to find out whether there are more entries in the stream.
096 * @exception ClassNotFoundException if the exception was thrown by the underlying stream.
097 *
098 * @override Never
099 */
100 public LogEntry readEntry() throws IOException, ClassNotFoundException {
101
102 while (true) {
103 try {
104 LogEntry le = (LogEntry)m_oisSource.readObject();
105
106 if ((m_lefFilter == null) || (m_lefFilter.accept(le))) {
107 return le;
108 }
109 }
110 catch (StreamCorruptedException sce) {
111 m_oisSource = new ObjectInputStream(m_isSource);
112 }
113 }
114 }
115 }