    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     */
    019    package org.apache.commons.compress.archivers;
    020
    021    import java.io.File;
    022    import java.io.IOException;
    023    import java.io.OutputStream;
    024
    025    /**
    026     * Archive output stream implementations are expected to override the
    027     * {@link #write(byte[], int, int)} method to improve performance.
    028     * They should also override {@link #close()} to ensure that any necessary
    029     * trailers are added.
    030     *
    031     * <p>
    032     * The normal sequence of calls for working with ArchiveOutputStreams is:
    033     * + create ArchiveOutputStream object
    034     * + write SFX header (optional, Zip only)
    035     * + repeat as needed:
    036     *      - putArchiveEntry() (writes entry header)
    037     *      - write() (writes entry data)
    038     *      - closeArchiveEntry() (closes entry)
    039     * + finish() (ends the addition of entries)
    040     * + write additional data if format supports it (optional)
    041     * + close()
    042     * </p>
    043     *
    044     * <p>
    045     * Example usage:<br/>
    046     * TBA
    047     * </p>
    048     */
    049    public abstract class ArchiveOutputStream extends OutputStream {
    050
    051        /** Temporary buffer used for the {@link #write(int)} method */
    052        private final byte[] oneByte = new byte[1];
    053        static final int BYTE_MASK = 0xFF;
    054
    055        /** holds the number of bytes read in this stream */
    056        private int bytesRead = 0;
    057        // Methods specific to ArchiveOutputStream
    058
    059        /**
    060         * Writes the headers for an archive entry to the output stream.
    061         * The caller must then write the content to the stream and call
    062         * {@link #closeArchiveEntry()} to complete the process.
    063         *
    064         * @param entry describes the entry
    065         * @throws IOException
    066         */
    067        public abstract void putArchiveEntry(ArchiveEntry entry) throws IOException;
    068
    069        /**
    070         * Closes the archive entry, writing any trailer information that may
    071         * be required.
    072         * @throws IOException
    073         */
    074        public abstract void closeArchiveEntry() throws IOException;
    075
    076        /**
    077         * Finishes the addition of entries to this stream, without closing it.
    078         * Additional data can be written, if the format supports it.
    079         *
    080         * The finish() method throws an Exception if the user forgets to close the entry
    081         * .
    082         * @throws IOException
    083         */
    084        public abstract void finish() throws IOException;
    085
    086        /**
    087         * Create an archive entry using the inputFile and entryName provided.
    088         *
    089         * @param inputFile
    090         * @param entryName
    091         * @return the ArchiveEntry set up with details from the file
    092         *
    093         * @throws IOException
    094         */
    095        public abstract ArchiveEntry createArchiveEntry(File inputFile, String entryName) throws IOException;
    096
    097        // Generic implementations of OutputStream methods that may be useful to sub-classes
    098
    099        /**
    100         * Writes a byte to the current archive entry.
    101         *
    102         * This method simply calls write( byte[], 0, 1 ).
    103         *
    104         * MUST be overridden if the {@link #write(byte[], int, int)} method
    105         * is not overridden; may be overridden otherwise.
    106         *
    107         * @param b The byte to be written.
    108         * @throws IOException on error
    109         */
    110        public void write(int b) throws IOException {
    111            oneByte[0] = (byte) (b & BYTE_MASK);
    112            write(oneByte, 0, 1);
    113        }
    114
    115        /**
    116         * Increments the counter of already read bytes.
    117         * Doesn't increment if the EOF has been hit (read == -1)
    118         *
    119         * @param read the number of bytes read
    120         */
    121        protected void count(int read) {
    122            if(read != -1) {
    123                bytesRead = bytesRead + read;
    124            }
    125        }
    126
    127        /**
    128         * Returns the current number of bytes read from this stream.
    129         * @return the number of read bytes
    130         */
    131        public int getCount() {
    132            return bytesRead;
    133        }
    134    }