001    /*
002     * CPXOutputStream.java
003     *
004     *
005     *  The Salamander Project - 2D and 3D graphics libraries in Java
006     *  Copyright (C) 2004 Mark McKay
007     *
008     *  This library is free software; you can redistribute it and/or
009     *  modify it under the terms of the GNU Lesser General Public
010     *  License as published by the Free Software Foundation; either
011     *  version 2.1 of the License, or (at your option) any later version.
012     *
013     *  This library is distributed in the hope that it will be useful,
014     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
015     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016     *  Lesser General Public License for more details.
017     *
018     *  You should have received a copy of the GNU Lesser General Public
019     *  License along with this library; if not, write to the Free Software
020     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021     *
022     *  Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
023     *  projects can be found at http://www.kitfox.com
024     *
025     * Created on February 12, 2004, 12:50 PM
026     */
027    
028    package com.kitfox.svg.xml.cpx;
029    
030    import java.io.*;
031    import java.util.zip.*;
032    import java.security.*;
033    import javax.crypto.*;
034    
035    /**
036     * @author Mark McKay
037     * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
038     */
039    public class CPXOutputStream extends FilterOutputStream implements CPXConsts {
040    
041        Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
042    
043        /** Creates a new instance of CPXOutputStream */
044        public CPXOutputStream(OutputStream os) throws IOException {
045            super(os);
046    
047            //Write magic number
048            os.write(MAGIC_NUMBER);
049        }
050    
051        /**
052         * Writes the specified <code>byte</code> to this output stream.
053         * <p>
054         * The <code>write</code> method of <code>FilterOutputStream</code>
055         * calls the <code>write</code> method of its underlying output stream,
056         * that is, it performs <tt>out.write(b)</tt>.
057         * <p>
058         * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
059         *
060         * @param      b   the <code>byte</code>.
061         * @exception  IOException  if an I/O error occurs.
062         */
063        public void write(int b) throws IOException {
064            final byte[] buf = new byte[1];
065            buf[0] = (byte)b;
066            write(buf, 0, 1);
067        }
068    
069        /**
070         * Writes <code>b.length</code> bytes to this output stream.
071         * <p>
072         * The <code>write</code> method of <code>FilterOutputStream</code>
073         * calls its <code>write</code> method of three arguments with the
074         * arguments <code>b</code>, <code>0</code>, and
075         * <code>b.length</code>.
076         * <p>
077         * Note that this method does not call the one-argument
078         * <code>write</code> method of its underlying stream with the single
079         * argument <code>b</code>.
080         *
081         * @param      b   the data to be written.
082         * @exception  IOException  if an I/O error occurs.
083         * @see        java.io.FilterOutputStream#write(byte[], int, int)
084         */
085        public void write(byte b[]) throws IOException {
086            write(b, 0, b.length);
087        }
088    
089        byte[] deflateBuffer = new byte[2048];
090    
091        /**
092         * Writes <code>len</code> bytes from the specified
093         * <code>byte</code> array starting at offset <code>off</code> to
094         * this output stream.
095         * <p>
096         * The <code>write</code> method of <code>FilterOutputStream</code>
097         * calls the <code>write</code> method of one argument on each
098         * <code>byte</code> to output.
099         * <p>
100         * Note that this method does not call the <code>write</code> method
101         * of its underlying input stream with the same arguments. Subclasses
102         * of <code>FilterOutputStream</code> should provide a more efficient
103         * implementation of this method.
104         *
105         * @param      b     the data.
106         * @param      off   the start offset in the data.
107         * @param      len   the number of bytes to write.
108         * @exception  IOException  if an I/O error occurs.
109         * @see        java.io.FilterOutputStream#write(int)
110         */
111        public void write(byte b[], int off, int len) throws IOException
112        {
113            deflater.setInput(b, off, len);
114    
115            processAllData();
116            /*
117            int numDeflatedBytes;
118            while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
119            {
120    //            byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
121    //            out.write(cipherBytes);
122    out.write(deflateBuffer, 0, numDeflatedBytes);
123            }
124            */
125        }
126    
127        protected void processAllData() throws IOException
128        {
129            int numDeflatedBytes;
130            while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
131            {
132    //            byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
133    //            out.write(cipherBytes);
134    out.write(deflateBuffer, 0, numDeflatedBytes);
135            }
136        }
137    
138        /**
139         * Flushes this output stream and forces any buffered output bytes
140         * to be written out to the stream.
141         * <p>
142         * The <code>flush</code> method of <code>FilterOutputStream</code>
143         * calls the <code>flush</code> method of its underlying output stream.
144         *
145         * @exception  IOException  if an I/O error occurs.
146         * @see        java.io.FilterOutputStream#out
147         */
148        public void flush() throws IOException {
149            out.flush();
150        }
151    
152        /**
153         * Closes this output stream and releases any system resources
154         * associated with the stream.
155         * <p>
156         * The <code>close</code> method of <code>FilterOutputStream</code>
157         * calls its <code>flush</code> method, and then calls the
158         * <code>close</code> method of its underlying output stream.
159         *
160         * @exception  IOException  if an I/O error occurs.
161         * @see        java.io.FilterOutputStream#flush()
162         * @see        java.io.FilterOutputStream#out
163         */
164        public void close() throws IOException {
165            deflater.finish();
166            processAllData();
167    
168            try {
169              flush();
170            } catch (IOException ignored) {
171            }
172            out.close();
173        }
174    }