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