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    /** Creates a new instance of CPXOutputStream */
051    public CPXOutputStream(OutputStream os) throws IOException {
052        super(os);
053
054        //Write magic number
055        os.write(MAGIC_NUMBER);
056    }
057
058    /**
059     * Writes the specified <code>byte</code> to this output stream.
060     * <p>
061     * The <code>write</code> method of <code>FilterOutputStream</code>
062     * calls the <code>write</code> method of its underlying output stream,
063     * that is, it performs <tt>out.write(b)</tt>.
064     * <p>
065     * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
066     *
067     * @param      b   the <code>byte</code>.
068     * @exception  IOException  if an I/O error occurs.
069     */
070    public void write(int b) throws IOException {
071        final byte[] buf = new byte[1];
072        buf[0] = (byte)b;
073        write(buf, 0, 1);
074    }
075
076    /**
077     * Writes <code>b.length</code> bytes to this output stream.
078     * <p>
079     * The <code>write</code> method of <code>FilterOutputStream</code>
080     * calls its <code>write</code> method of three arguments with the
081     * arguments <code>b</code>, <code>0</code>, and
082     * <code>b.length</code>.
083     * <p>
084     * Note that this method does not call the one-argument
085     * <code>write</code> method of its underlying stream with the single
086     * argument <code>b</code>.
087     *
088     * @param      b   the data to be written.
089     * @exception  IOException  if an I/O error occurs.
090     * @see        java.io.FilterOutputStream#write(byte[], int, int)
091     */
092    public void write(byte b[]) throws IOException {
093        write(b, 0, b.length);
094    }
095
096    byte[] deflateBuffer = new byte[2048];
097
098    /**
099     * Writes <code>len</code> bytes from the specified
100     * <code>byte</code> array starting at offset <code>off</code> to
101     * this output stream.
102     * <p>
103     * The <code>write</code> method of <code>FilterOutputStream</code>
104     * calls the <code>write</code> method of one argument on each
105     * <code>byte</code> to output.
106     * <p>
107     * Note that this method does not call the <code>write</code> method
108     * of its underlying input stream with the same arguments. Subclasses
109     * of <code>FilterOutputStream</code> should provide a more efficient
110     * implementation of this method.
111     *
112     * @param      b     the data.
113     * @param      off   the start offset in the data.
114     * @param      len   the number of bytes to write.
115     * @exception  IOException  if an I/O error occurs.
116     * @see        java.io.FilterOutputStream#write(int)
117     */
118    public void write(byte b[], int off, int len) throws IOException
119    {
120        deflater.setInput(b, off, len);
121
122        processAllData();
123        /*
124        int numDeflatedBytes;
125        while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
126        {
127//            byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
128//            out.write(cipherBytes);
129out.write(deflateBuffer, 0, numDeflatedBytes);
130        }
131        */
132    }
133
134    protected void processAllData() throws IOException
135    {
136        int numDeflatedBytes;
137        while ((numDeflatedBytes = deflater.deflate(deflateBuffer)) != 0)
138        {
139//            byte[] cipherBuf = cipher.update(deflateBuffer, 0, numDeflatedBytes);
140//            out.write(cipherBytes);
141out.write(deflateBuffer, 0, numDeflatedBytes);
142        }
143    }
144
145    /**
146     * Flushes this output stream and forces any buffered output bytes
147     * to be written out to the stream.
148     * <p>
149     * The <code>flush</code> method of <code>FilterOutputStream</code>
150     * calls the <code>flush</code> method of its underlying output stream.
151     *
152     * @exception  IOException  if an I/O error occurs.
153     * @see        java.io.FilterOutputStream#out
154     */
155    public void flush() throws IOException {
156        out.flush();
157    }
158
159    /**
160     * Closes this output stream and releases any system resources
161     * associated with the stream.
162     * <p>
163     * The <code>close</code> method of <code>FilterOutputStream</code>
164     * calls its <code>flush</code> method, and then calls the
165     * <code>close</code> method of its underlying output stream.
166     *
167     * @exception  IOException  if an I/O error occurs.
168     * @see        java.io.FilterOutputStream#flush()
169     * @see        java.io.FilterOutputStream#out
170     */
171    public void close() throws IOException {
172        deflater.finish();
173        processAllData();
174
175        try {
176          flush();
177        } catch (IOException ignored) {
178        }
179        out.close();
180    }
181}