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