001    /*
002    Copyright (c) 1996-2011, Damon Hart-Davis
003    All rights reserved.
004    
005    Redistribution and use in source and binary forms, with or without
006    modification, are permitted provided that the following conditions are
007    met:
008    
009      * Redistributions of source code must retain the above copyright
010        notice, this list of conditions and the following disclaimer.
011    
012      * Redistributions in binary form must reproduce the above copyright
013        notice, this list of conditions and the following disclaimer in the
014        documentation and/or other materials provided with the
015        distribution.
016    
017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028    */
029    package org.hd.d.pg2k.svrCore;
030    
031    import java.io.IOException;
032    import java.io.OutputStream;
033    import java.util.zip.Deflater;
034    import java.util.zip.DeflaterOutputStream;
035    
036    /**Like GZIPOutputStream but no GZIP header or checksum.
037     * This is meant to give maximum compression and assumes error
038     * checking/recovery is done elsewhere.
039     */
040    public final class DefOutputStream extends DeflaterOutputStream
041        {
042        /**Creates a new output stream with the specified buffer size.
043         * Forces use of the best possible compression at the possible
044         * expense of CPU time.
045         * <p>
046         * This compressed stream is wrapped with neither GZIP nor ZLIB
047         * headers/checksums to minimise overheads; we'd better be doing
048         * error detection and correction elsewhere!
049         *
050         * @param out the output stream
051         * @param size the output buffer size;
052         *     changing this from the default of 512 bytes is unlikely
053         *     to improve performance
054         */
055        private DefOutputStream(final OutputStream out, final int size)
056            // throws IOException
057            { super(out, new Deflater(Deflater.BEST_COMPRESSION, true), size); }
058    
059        /**Creates a new output stream with a default buffer size.
060         * @param out the output stream
061         */
062        public DefOutputStream(final OutputStream out)
063            // throws IOException
064            { this(out, 512); }
065    
066        /**Writes array of bytes to the compressed output stream; blocking.
067         * @exception IOException   if an I/O error has occurred
068         */
069        @Override
070        public synchronized void write(final byte[] buf, final int off, final int len)
071            throws IOException
072            { super.write(buf, off, len); }
073    
074        /**Finishes writing compressed data to the output stream without closing it.
075         * @exception IOException   if an I/O error has occurred
076         */
077        @Override
078        public synchronized void finish()
079            throws IOException
080            {
081            if(!def.finished())
082                {
083                def.finish();
084                while(!def.finished()) { deflate(); }
085                }
086            }
087    
088        /**Writes remaining compressed data to the output stream and closes it.
089         * Frees underlying (memory and non-memory) resources also.
090         * @exception IOException   if an I/O error has occurred
091         */
092        @Override
093        public synchronized void close()
094            throws IOException
095            {
096            finish();
097            def.end(); // Ensure that resources are freed immediately; not waiting for finalize().
098            out.close();
099            }
100        }