001/*
002 * SVG Salamander
003 * Copyright (c) 2004, Mark McKay
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or 
007 * without modification, are permitted provided that the following
008 * conditions are met:
009 *
010 *   - Redistributions of source code must retain the above 
011 *     copyright notice, this list of conditions and the following
012 *     disclaimer.
013 *   - Redistributions in binary form must reproduce the above
014 *     copyright notice, this list of conditions and the following
015 *     disclaimer in the documentation and/or other materials 
016 *     provided with the distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
029 * OF THE POSSIBILITY OF SUCH DAMAGE. 
030 * 
031 * Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
032 * projects can be found at http://www.kitfox.com
033 *
034 * Created on February 12, 2004, 12:50 PM
035 */
036
037package com.kitfox.svg.xml.cpx;
038
039import java.io.*;
040import java.util.zip.*;
041
042/**
043 * @author Mark McKay
044 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
045 */
046public class CPXOutputStream extends FilterOutputStream implements CPXConsts {
047
048    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
049
050    /** 
051     * Creates a new instance of CPXOutputStream
052     * @param os
053     * @throws java.io.IOException
054     */
055    public CPXOutputStream(OutputStream os) throws IOException {
056        super(os);
057
058        //Write magic number
059        os.write(MAGIC_NUMBER);
060    }
061
062    /**
063     * Writes the specified <code>byte</code> to this output stream.
064     * <p>
065     * The <code>write</code> method of <code>FilterOutputStream</code>
066     * calls the <code>write</code> method of its underlying output stream,
067     * that is, it performs <tt>out.write(b)</tt>.
068     * <p>
069     * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
070     *
071     * @param      b   the <code>byte</code>.
072     * @exception  IOException  if an I/O error occurs.
073     */
074    @Override
075    public void write(int b) throws IOException {
076        final byte[] buf = new byte[1];
077        buf[0] = (byte)b;
078        write(buf, 0, 1);
079    }
080
081    /**
082     * Writes <code>b.length</code> bytes to this output stream.
083     * <p>
084     * The <code>write</code> method of <code>FilterOutputStream</code>
085     * calls its <code>write</code> method of three arguments with the
086     * arguments <code>b</code>, <code>0</code>, and
087     * <code>b.length</code>.
088     * <p>
089     * Note that this method does not call the one-argument
090     * <code>write</code> method of its underlying stream with the single
091     * argument <code>b</code>.
092     *
093     * @param      b   the data to be written.
094     * @exception  IOException  if an I/O error occurs.
095     * @see        java.io.FilterOutputStream#write(byte[], int, int)
096     */
097    @Override
098    public void write(byte b[]) throws IOException {
099        write(b, 0, b.length);
100    }
101
102    byte[] deflateBuffer = new byte[2048];
103
104    /**
105     * Writes <code>len</code> bytes from the specified
106     * <code>byte</code> array starting at offset <code>off</code> to
107     * this output stream.
108     * <p>
109     * The <code>write</code> method of <code>FilterOutputStream</code>
110     * calls the <code>write</code> method of one argument on each
111     * <code>byte</code> to output.
112     * <p>
113     * Note that this method does not call the <code>write</code> method
114     * of its underlying input stream with the same arguments. Subclasses
115     * of <code>FilterOutputStream</code> should provide a more efficient
116     * implementation of this method.
117     *
118     * @param      b     the data.
119     * @param      off   the start offset in the data.
120     * @param      len   the number of bytes to write.
121     * @exception  IOException  if an I/O error occurs.
122     * @see        java.io.FilterOutputStream#write(int)
123     */
124    @Override
125    public void write(byte b[], int off, int len) throws IOException
126    {
127        deflater.setInput(b, off, len);
128
129        processAllData();
130        /*
131        int numDeflatedBytes;
132        while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
133        {
134//            byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
135//            out.write(cipherBytes);
136out.write(deflateBuffer, 0, numDeflatedBytes);
137        }
138        */
139    }
140
141    protected void processAllData() throws IOException
142    {
143        int numDeflatedBytes;
144        while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
145        {
146//            byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
147//            out.write(cipherBytes);
148out.write(deflateBuffer, 0, numDeflatedBytes);
149        }
150    }
151
152    /**
153     * Flushes this output stream and forces any buffered output bytes
154     * to be written out to the stream.
155     * <p>
156     * The <code>flush</code> method of <code>FilterOutputStream</code>
157     * calls the <code>flush</code> method of its underlying output stream.
158     *
159     * @exception  IOException  if an I/O error occurs.
160     * @see        java.io.FilterOutputStream#out
161     */
162    @Override
163    public void flush() throws IOException {
164        out.flush();
165    }
166
167    /**
168     * Closes this output stream and releases any system resources
169     * associated with the stream.
170     * <p>
171     * The <code>close</code> method of <code>FilterOutputStream</code>
172     * calls its <code>flush</code> method, and then calls the
173     * <code>close</code> method of its underlying output stream.
174     *
175     * @exception  IOException  if an I/O error occurs.
176     * @see        java.io.FilterOutputStream#flush()
177     * @see        java.io.FilterOutputStream#out
178     */
179    @Override
180    public void close() throws IOException {
181        deflater.finish();
182        processAllData();
183
184        try {
185          flush();
186        } catch (IOException ignored) {
187        }
188        out.close();
189    }
190}