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    }