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 }