    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 written to this stream */
    056        private long bytesWritten = 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 written bytes.
    117         * Doesn't increment if the EOF has been hit (read == -1)
    118         *
    119         * @param written the number of bytes written
    120         */
    121        protected void count(int written) {
    122            count((long) written);
    123        }
    124
    125        /**
    126         * Increments the counter of already written bytes.
    127         * Doesn't increment if the EOF has been hit (read == -1)
    128         *
    129         * @param written the number of bytes written
    130         * @since Apache Commons Compress 1.1
    131         */
    132        protected void count(long written) {
    133            if (written != -1) {
    134                bytesWritten = bytesWritten + written;
    135            }
    136        }
    137
    138        /**
    139         * Returns the current number of bytes written to this stream.
    140         * @return the number of written bytes
    141         * @deprecated this method may yield wrong results for large
    142         * archives, use #getBytesWritten instead
    143         */
    144        public int getCount() {
    145            return (int) bytesWritten;
    146        }
    147
    148        /**
    149         * Returns the current number of bytes written to this stream.
    150         * @return the number of written bytes
    151         * @since Apache Commons Compress 1.1
    152         */
    153        public long getBytesWritten() {
    154            return bytesWritten;
    155        }
    156
    157        /**
    158         * Whether this stream is able to write the given entry.
    159         *
    160         * <p>Some archive formats support variants or details that are
    161         * not supported (yet).</p>
    162         *
    163         * <p>This implementation always returns true.
    164         * @since Apache Commons Compress 1.1
    165         */
    166        public boolean canWriteEntryData(ArchiveEntry ae) {
    167            return true;
    168        }
    169    }