001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.compress.archivers;
020
021import java.io.IOException;
022import java.io.InputStream;
023
024/**
025 * Archive input streams <b>MUST</b> override the
026 * {@link #read(byte[], int, int)} - or {@link #read()} -
027 * method so that reading from the stream generates EOF for the end of
028 * data in each entry as well as at the end of the file proper.
029 * <p>
030 * The {@link #getNextEntry()} method is used to reset the input stream
031 * ready for reading the data from the next entry.
032 * <p>
033 * The input stream classes must also implement a method with the signature:
034 * <pre>
035 * public static boolean matches(byte[] signature, int length)
036 * </pre>
037 * which is used by the {@link ArchiveStreamFactory} to autodetect
038 * the archive type from the first few bytes of a stream.
039 *
040 * @param <E> The type of {@link ArchiveEntry} produced.
041 */
042public abstract class ArchiveInputStream<E extends ArchiveEntry> extends InputStream {
043
044    private static final int BYTE_MASK = 0xFF;
045    private final byte[] single = new byte[1];
046
047    /** Holds the number of bytes read in this stream */
048    private long bytesRead;
049
050    /**
051     * Whether this stream is able to read the given entry.
052     *
053     * <p>
054     * Some archive formats support variants or details that are not supported (yet).
055     * </p>
056     *
057     * @param archiveEntry
058     *            the entry to test
059     * @return This implementation always returns true.
060     *
061     * @since 1.1
062     */
063    public boolean canReadEntryData(final ArchiveEntry archiveEntry) {
064        return true;
065    }
066
067    /**
068     * Increments the counter of already read bytes.
069     * Doesn't increment if the EOF has been hit (read == -1)
070     *
071     * @param read the number of bytes read
072     */
073    protected void count(final int read) {
074        count((long) read);
075    }
076
077    /**
078     * Increments the counter of already read bytes.
079     * Doesn't increment if the EOF has been hit (read == -1)
080     *
081     * @param read the number of bytes read
082     * @since 1.1
083     */
084    protected void count(final long read) {
085        if (read != -1) {
086            bytesRead = bytesRead + read;
087        }
088    }
089
090    /**
091     * Returns the current number of bytes read from this stream.
092     * @return the number of read bytes
093     * @since 1.1
094     */
095    public long getBytesRead() {
096        return bytesRead;
097    }
098
099    /**
100     * Returns the current number of bytes read from this stream.
101     * @return the number of read bytes
102     * @deprecated this method may yield wrong results for large
103     * archives, use #getBytesRead instead
104     */
105    @Deprecated
106    public int getCount() {
107        return (int) bytesRead;
108    }
109
110    /**
111     * Returns the next Archive Entry in this Stream.
112     *
113     * @return the next entry,
114     *         or {@code null} if there are no more entries
115     * @throws IOException if the next entry could not be read
116     */
117    public abstract E getNextEntry() throws IOException;
118
119    /**
120     * Decrements the counter of already read bytes.
121     *
122     * @param pushedBack the number of bytes pushed back.
123     * @since 1.1
124     */
125    protected void pushedBackBytes(final long pushedBack) {
126        bytesRead -= pushedBack;
127    }
128
129    /**
130     * Reads a byte of data. This method will block until enough input is
131     * available.
132     *
133     * Simply calls the {@link #read(byte[], int, int)} method.
134     *
135     * MUST be overridden if the {@link #read(byte[], int, int)} method
136     * is not overridden; may be overridden otherwise.
137     *
138     * @return the byte read, or -1 if end of input is reached
139     * @throws IOException
140     *             if an I/O error has occurred
141     */
142    @Override
143    public int read() throws IOException {
144        final int num = read(single, 0, 1);
145        return num == -1 ? -1 : single[0] & BYTE_MASK;
146    }
147
148}