diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/org/apache/fop/pdf/ASCII85Filter.java | 32 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/ASCIIHexFilter.java | 20 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/DCTFilter.java | 10 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/FlateFilter.java | 11 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/InMemoryStreamCache.java | 104 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFFilter.java | 6 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFICCStream.java | 3 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFStream.java | 49 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFT1Stream.java | 4 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFTTFStream.java | 4 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/StreamCache.java | 84 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/TempFileStreamCache.java | 132 | ||||
-rw-r--r-- | src/org/apache/fop/tools/AreaTreeBuilder.java | 5 | ||||
-rw-r--r-- | src/org/apache/fop/util/StreamUtilities.java | 147 |
14 files changed, 543 insertions, 68 deletions
diff --git a/src/org/apache/fop/pdf/ASCII85Filter.java b/src/org/apache/fop/pdf/ASCII85Filter.java index 40706e968..84e03f0eb 100644 --- a/src/org/apache/fop/pdf/ASCII85Filter.java +++ b/src/org/apache/fop/pdf/ASCII85Filter.java @@ -9,6 +9,7 @@ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.*; public class ASCII85Filter extends PDFFilter { private static final char ASCII85_ZERO = 'z'; @@ -30,9 +31,7 @@ public class ASCII85Filter extends PDFFilter { return null; } - public byte[] encode(byte[] data) { - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + public void encode(InputStream in, OutputStream out, int length) throws IOException { int i; int total = 0; @@ -40,16 +39,16 @@ public class ASCII85Filter extends PDFFilter { // first encode the majority of the data // each 4 byte group becomes a 5 byte group - for (i = 0; i + 3 < data.length; i += 4) { + for (i = 0; i + 3 < length; i += 4) { - long val = ((data[i] << 24) + long val = ((in.read() << 24) & 0xff000000L) // note: must have the L at the - + ((data[i + 1] << 16) & 0xff0000L) // end, otherwise you get into - + ((data[i + 2] << 8) & 0xff00L) // weird signed value problems - + (data[i + 3] & 0xffL); // cause we're using a full 32 bits + + ((in.read() << 16) & 0xff0000L) // end, otherwise you get into + + ((in.read() << 8) & 0xff00L) // weird signed value problems + + (in.read() & 0xffL); // cause we're using a full 32 bits byte[] conv = convertWord(val); - buffer.write(conv, 0, conv.length); + out.write(conv, 0, conv.length); } @@ -57,12 +56,12 @@ public class ASCII85Filter extends PDFFilter { // with n leftover bytes, we append 0 bytes to make a full group of 4 // then convert like normal (except not applying the special zero rule) // and write out the first n+1 bytes from the result - if (i < data.length) { - int n = data.length - i; + if (i < length) { + int n = length - i; byte[] lastdata = new byte[4]; for (int j = 0; j < 4; j++) { if (j < n) { - lastdata[j] = data[i++]; + lastdata[j] = (byte)in.read(); } else { lastdata[j] = 0; } @@ -82,18 +81,15 @@ public class ASCII85Filter extends PDFFilter { } } // assert n+1 <= 5 - buffer.write(conv, 0, n + 1); + out.write(conv, 0, n + 1); // System.out.println("ASCII85 end of data was "+n+" bytes long"); } // finally write the two character end of data marker - buffer.write(ASCII85_EOD.getBytes(), 0, + out.write(ASCII85_EOD.getBytes(), 0, ASCII85_EOD.getBytes().length); - byte[] result = buffer.toByteArray(); - - // assert that we have the correct outgoing length /* * int in = (data.length % 4); @@ -103,8 +99,8 @@ public class ASCII85Filter extends PDFFilter { * System.out.println(" inlength = "+data.length+" inlength % 4 = "+(data.length % 4)+" outlength = "+(result.length-ASCII85_EOD.getBytes().length)+" outlength % 5 = "+((result.length-ASCII85_EOD.getBytes().length) % 5)); * } */ - return result; + out.close(); } /** diff --git a/src/org/apache/fop/pdf/ASCIIHexFilter.java b/src/org/apache/fop/pdf/ASCIIHexFilter.java index 775a7fcb4..4e81bfc6e 100644 --- a/src/org/apache/fop/pdf/ASCIIHexFilter.java +++ b/src/org/apache/fop/pdf/ASCIIHexFilter.java @@ -8,6 +8,7 @@ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.*; public class ASCIIHexFilter extends PDFFilter { private static final String ASCIIHEX_EOD = ">"; @@ -21,19 +22,16 @@ public class ASCIIHexFilter extends PDFFilter { return null; } - public byte[] encode(byte[] data) { - - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < data.length; i++) { - int val = (int)(data[i] & 0xFF); + public void encode(InputStream in, OutputStream out, int length) throws IOException { + Writer writer = new OutputStreamWriter(out); + for (int i = 0; i < length; i++) { + int val = (int)(in.read() & 0xFF); if (val < 16) - buffer.append("0"); - buffer.append(Integer.toHexString(val)); + writer.write("0"); + writer.write(Integer.toHexString(val)); } - buffer.append(ASCIIHEX_EOD); - - return buffer.toString().getBytes(); - + writer.write(ASCIIHEX_EOD); + writer.close(); } } diff --git a/src/org/apache/fop/pdf/DCTFilter.java b/src/org/apache/fop/pdf/DCTFilter.java index 9d59a676c..6f0abf5d6 100644 --- a/src/org/apache/fop/pdf/DCTFilter.java +++ b/src/org/apache/fop/pdf/DCTFilter.java @@ -7,9 +7,11 @@ package org.apache.fop.pdf; +import org.apache.fop.util.StreamUtilities; + import java.io.ByteArrayOutputStream; import java.io.IOException; - +import java.io.*; /** * DCT Filter class. Right now it is just used as a dummy filter flag so @@ -28,8 +30,10 @@ public class DCTFilter extends PDFFilter { return null; } - public byte[] encode(byte[] data) { - return data; + public void encode(InputStream in, OutputStream out, int length) throws IOException { + StreamUtilities.streamCopy(in, out, length); + out.close(); } + } diff --git a/src/org/apache/fop/pdf/FlateFilter.java b/src/org/apache/fop/pdf/FlateFilter.java index f439b9cc0..d3d5b3d35 100644 --- a/src/org/apache/fop/pdf/FlateFilter.java +++ b/src/org/apache/fop/pdf/FlateFilter.java @@ -7,9 +7,12 @@ package org.apache.fop.pdf; +import org.apache.fop.util.StreamUtilities; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.DeflaterOutputStream; +import java.io.*; /** * A filter to deflate a stream. Note that the attributes for @@ -66,13 +69,12 @@ public class FlateFilter extends PDFFilter { * because these attributes are not supported. So the DecodeParms * should be retrieved after calling this method. */ - public byte[] encode(byte[] data) { - ByteArrayOutputStream outArrayStream = new ByteArrayOutputStream(); + public void encode(InputStream in, OutputStream out, int length) throws IOException { _predictor = PREDICTION_NONE; try { DeflaterOutputStream compressedStream = - new DeflaterOutputStream(outArrayStream); - compressedStream.write(data, 0, data.length); + new DeflaterOutputStream(out); + StreamUtilities.streamCopy(in, compressedStream, length); compressedStream.flush(); compressedStream.close(); } catch (IOException e) { @@ -80,7 +82,6 @@ public class FlateFilter extends PDFFilter { // + e.getMessage(), e); } - return outArrayStream.toByteArray(); } public void setPredictor(int predictor) throws PDFFilterException { diff --git a/src/org/apache/fop/pdf/InMemoryStreamCache.java b/src/org/apache/fop/pdf/InMemoryStreamCache.java new file mode 100644 index 000000000..c39e866d0 --- /dev/null +++ b/src/org/apache/fop/pdf/InMemoryStreamCache.java @@ -0,0 +1,104 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.pdf; + +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * StreamCache implementation that uses temporary files rather than heap. + */ +public class InMemoryStreamCache extends StreamCache { + + /** + * The current output stream. + */ + private ByteArrayOutputStream output; + + /** + * Creates a new InMemoryStreamCache. + */ + public InMemoryStreamCache() { + } + + /** + * Get the current OutputStream. Do not store it - it may change + * from call to call. + */ + public OutputStream getOutputStream() throws IOException { + if (output == null) + output = new ByteArrayOutputStream(); + return output; + } + + /** + * Filter the cache with the supplied PDFFilter. + */ + public void applyFilter(PDFFilter filter) throws IOException { + if (output == null) + return; + + output.close(); + + // make inputstream from copy of outputted bytes + int size = getSize(); + ByteArrayInputStream input = + new ByteArrayInputStream(output.toByteArray()); + + // reset output + output.reset(); + + // run filter + filter.encode(input, output, size); + input.close(); + output.close(); + } + + /** + * Outputs the cached bytes to the given stream. + */ + public void outputStreamData(OutputStream stream) throws IOException { + if (output == null) + return; + + output.writeTo(stream); + } + + /** + * Returns the current size of the stream. + */ + public int getSize() throws IOException { + if (output == null) + return 0; + else + return output.size(); + } + + /** + * Closes the cache and frees resources. + */ + public void close() throws IOException { + if (output != null) { + output.close(); + output = null; + } + } + + /** + * Clears and resets the cache. + */ + public void reset() throws IOException { + if (output != null) { + output.close(); + output = null; + } + } +} diff --git a/src/org/apache/fop/pdf/PDFFilter.java b/src/org/apache/fop/pdf/PDFFilter.java index 1cb6ce18c..4572c28c4 100644 --- a/src/org/apache/fop/pdf/PDFFilter.java +++ b/src/org/apache/fop/pdf/PDFFilter.java @@ -11,6 +11,8 @@ package org.apache.fop.pdf; +import java.io.*; + public abstract class PDFFilter { /* * These are no longer needed, but are here as a reminder about what @@ -60,8 +62,6 @@ public abstract class PDFFilter { /** * encode the given data with the filter */ - public abstract byte[] encode(byte[] data); - - + public abstract void encode(InputStream in, OutputStream out, int length) throws IOException; } diff --git a/src/org/apache/fop/pdf/PDFICCStream.java b/src/org/apache/fop/pdf/PDFICCStream.java index 7890b51a9..55d444aca 100644 --- a/src/org/apache/fop/pdf/PDFICCStream.java +++ b/src/org/apache/fop/pdf/PDFICCStream.java @@ -11,7 +11,6 @@ import org.apache.fop.datatypes.ColorSpace; public class PDFICCStream extends PDFStream { private int origLength; private int len1, len3; - private byte[] originalData = null; private ColorSpace cs; @@ -43,7 +42,7 @@ public class PDFICCStream extends PDFStream { if (cs.getColorSpace() > 0) pb.append("/Alternate /").append(cs.getColorSpacePDFString()).append(" "); - pb.append("/Length ").append((_data.size() + 1)).append(" ").append(filterEntry); + pb.append("/Length ").append((_data.getSize() + 1)).append(" ").append(filterEntry); pb.append(" >>\n"); byte[] p = pb.toString().getBytes(); stream.write(p); diff --git a/src/org/apache/fop/pdf/PDFStream.java b/src/org/apache/fop/pdf/PDFStream.java index 1a268306c..20c3ef0cc 100644 --- a/src/org/apache/fop/pdf/PDFStream.java +++ b/src/org/apache/fop/pdf/PDFStream.java @@ -27,7 +27,7 @@ public class PDFStream extends PDFObject { /** * the stream of PDF commands */ - protected ByteArrayOutputStream _data; + protected StreamCache _data; /** * the filters that should be applied @@ -41,7 +41,11 @@ public class PDFStream extends PDFObject { */ public PDFStream(int number) { super(number); - _data = new ByteArrayOutputStream(); + try { + _data = StreamCache.createStreamCache(); + } catch (IOException ex) { + ex.printStackTrace(); + } _filters = new ArrayList(); } @@ -52,7 +56,7 @@ public class PDFStream extends PDFObject { */ public void add(String s) { try { - _data.write(s.getBytes()); + _data.getOutputStream().write(s.getBytes()); } catch (IOException ex) { ex.printStackTrace(); } @@ -130,21 +134,21 @@ public class PDFStream extends PDFObject { int g = (p >> 8) & 0xFF; int b = (p) & 0xFF; if (r < 16) { - _data.write('0'); + _data.getOutputStream().write('0'); } - _data.write(Integer.toHexString(r).getBytes()); + _data.getOutputStream().write(Integer.toHexString(r).getBytes()); if (g < 16) { - _data.write('0'); + _data.getOutputStream().write('0'); } - _data.write(Integer.toHexString(g).getBytes()); + _data.getOutputStream().write(Integer.toHexString(g).getBytes()); if (b < 16) { - _data.write('0'); + _data.getOutputStream().write('0'); } - _data.write(Integer.toHexString(b).getBytes()); - _data.write(' '); + _data.getOutputStream().write(Integer.toHexString(b).getBytes()); + _data.getOutputStream().write(' '); } } - _data.write(">\n".getBytes()); + _data.getOutputStream().write(">\n".getBytes()); } catch (IOException ex) { ex.printStackTrace(); } @@ -153,15 +157,22 @@ public class PDFStream extends PDFObject { public void setData(byte[] data) throws IOException { _data.reset(); - _data.write(data); + _data.getOutputStream().write(data); } + /* public byte[] getData() { return _data.toByteArray(); } + */ public int getDataLength() { - return _data.size(); + try { + return _data.getSize(); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } } @@ -188,14 +199,13 @@ public class PDFStream extends PDFObject { throw new RuntimeException(); } - // overload the base object method so we don't have to copy // byte arrays around so much protected int output(OutputStream stream) throws IOException { int length = 0; String filterEntry = applyFilters(); byte[] p = (this.number + " " + this.generation + " obj\n<< /Length " - + (_data.size() + 1) + " " + filterEntry + + (_data.getSize() + 1) + " " + filterEntry + " >>\n").getBytes(); stream.write(p); @@ -216,8 +226,9 @@ public class PDFStream extends PDFObject { byte[] p = "stream\n".getBytes(); stream.write(p); length += p.length; - _data.writeTo(stream); - length += _data.size(); + _data.outputStreamData(stream); + _data.close(); + length += _data.getSize(); p = "\nendstream\n".getBytes(); stream.write(p); length += p.length; @@ -243,9 +254,7 @@ public class PDFStream extends PDFObject { PDFFilter filter = (PDFFilter)_filters.get(count); // apply the filter encoding if neccessary if (!filter.isApplied()) { - byte[] tmp = filter.encode(_data.toByteArray()); - _data.reset(); - _data.write(tmp); + _data.applyFilter(filter); filter.setApplied(true); } // place the names in our local vector in reverse order diff --git a/src/org/apache/fop/pdf/PDFT1Stream.java b/src/org/apache/fop/pdf/PDFT1Stream.java index 8de99f260..c0f62380f 100644 --- a/src/org/apache/fop/pdf/PDFT1Stream.java +++ b/src/org/apache/fop/pdf/PDFT1Stream.java @@ -80,7 +80,7 @@ public class PDFT1Stream extends PDFStream { String filterEntry = applyFilters(); String preData = new String(this.number + " " + this.generation + " obj\n<< /Length " - + (_data.size() + 1) + " " + filterEntry + + (_data.getSize() + 1) + " " + filterEntry + " " + "/Length1 " + len1 + " /Length2 " + (origLength - len3 - len1) + " /Length3 " + len3 + " >>\n"); @@ -101,7 +101,7 @@ public class PDFT1Stream extends PDFStream { calcLengths(data); _data.reset(); // System.out.println("Writing " + size + " bytes of font data"); - _data.write(data, 0, size); + _data.getOutputStream().write(data, 0, size); } } diff --git a/src/org/apache/fop/pdf/PDFTTFStream.java b/src/org/apache/fop/pdf/PDFTTFStream.java index f56e5f587..386f1fec1 100644 --- a/src/org/apache/fop/pdf/PDFTTFStream.java +++ b/src/org/apache/fop/pdf/PDFTTFStream.java @@ -23,7 +23,7 @@ public class PDFTTFStream extends PDFStream { String filterEntry = applyFilters(); String preData = new String(this.number + " " + this.generation + " obj\n<< /Length " - + (_data.size() + 1) + " " + filterEntry + + (_data.getSize() + 1) + " " + filterEntry + " " + "/Length1 " + origLength + " >>\n"); @@ -41,7 +41,7 @@ public class PDFTTFStream extends PDFStream { public void setData(byte[] data, int size) throws java.io.IOException { _data.reset(); System.out.println("Writing " + size + " bytes of font data"); - _data.write(data, 0, size); + _data.getOutputStream().write(data, 0, size); } } diff --git a/src/org/apache/fop/pdf/StreamCache.java b/src/org/apache/fop/pdf/StreamCache.java new file mode 100644 index 000000000..f2d5b904a --- /dev/null +++ b/src/org/apache/fop/pdf/StreamCache.java @@ -0,0 +1,84 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.pdf; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.ArrayList; + +/** + * class used to store the bytes for a PDFStream. It's actually a generic + * cached byte array, along with a factory that returns either an + * in-memory or tempfile based implementation based on the global + * cacheToFile setting. + */ +public abstract class StreamCache { + + /** + * Global setting; controls whether to use tempfiles or not. + */ + private static boolean cacheToFile = false; + + /** + * Change the global cacheToFile flag. + */ + public static void setCacheToFile(boolean tizit) { + cacheToFile = tizit; + } + + /** + * Get the value of the global cacheToFile flag. + */ + public static boolean getCacheToFile() { + return cacheToFile; + } + + /** + * Get the correct implementation (based on cacheToFile) of + * StreamCache. + */ + public static StreamCache createStreamCache() throws IOException { + if (cacheToFile) + return new TempFileStreamCache(); + else + return new InMemoryStreamCache(); + } + + /** + * Get the current OutputStream. Do not store it - it may change + * from call to call. + */ + public abstract OutputStream getOutputStream() throws IOException; + + /** + * Filter the cache with the supplied PDFFilter. + */ + public abstract void applyFilter(PDFFilter filter) throws IOException; + + /** + * Outputs the cached bytes to the given stream. + */ + public abstract void outputStreamData(OutputStream stream) throws IOException; + + /** + * Returns the current size of the stream. + */ + public abstract int getSize() throws IOException; + + /** + * Closes the cache and frees resources. + */ + public abstract void close() throws IOException; + + /** + * Clears and resets the cache. + */ + public abstract void reset() throws IOException; +} + diff --git a/src/org/apache/fop/pdf/TempFileStreamCache.java b/src/org/apache/fop/pdf/TempFileStreamCache.java new file mode 100644 index 000000000..c4eb1c1a5 --- /dev/null +++ b/src/org/apache/fop/pdf/TempFileStreamCache.java @@ -0,0 +1,132 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.pdf; + +import org.apache.fop.util.StreamUtilities; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.File; + +/** + * StreamCache implementation that uses temporary files rather than heap. + */ +public class TempFileStreamCache extends StreamCache { + + /** + * The current output stream. + */ + private BufferedOutputStream output; + + /** + * The temp file. + */ + private File tempFile; + + /** + * Creates a new TempFileStreamCache. + */ + public TempFileStreamCache() throws IOException { + tempFile = File.createTempFile("org.apache.fop.pdf.StreamCache-", + ".temp"); + tempFile.deleteOnExit(); + } + + /** + * Get the current OutputStream. Do not store it - it may change + * from call to call. + */ + public OutputStream getOutputStream() throws IOException { + if (output == null) + output = new BufferedOutputStream( + new FileOutputStream(tempFile)); + return output; + } + + /** + * Filter the cache with the supplied PDFFilter. + */ + public void applyFilter(PDFFilter filter) throws IOException { + if (output == null) + return; + + output.close(); + output = null; + + // need a place to put results + File newTempFile = + File.createTempFile("org.apache.fop.pdf.StreamCache-", + ".temp"); + newTempFile.deleteOnExit(); + + // filter may not be buffered + BufferedInputStream input = + new BufferedInputStream(new FileInputStream(tempFile)); + BufferedOutputStream output = new BufferedOutputStream( + new FileOutputStream(newTempFile)); + filter.encode(input, output, (int) tempFile.length()); + input.close(); + output.close(); + tempFile.delete(); + tempFile = newTempFile; + } + + /** + * Outputs the cached bytes to the given stream. + */ + public void outputStreamData(OutputStream stream) throws IOException { + if (output == null) + return; + + output.close(); + output = null; + + // don't need a buffer because streamCopy is buffered + FileInputStream input = new FileInputStream(tempFile); + StreamUtilities.streamCopy(input, output); + input.close(); + } + + /** + * Returns the current size of the stream. + */ + public int getSize() throws IOException { + if (output != null) + output.flush(); + return (int) tempFile.length(); + } + + /** + * Closes the cache and frees resources. + */ + public void close() throws IOException { + if (output != null) { + output.close(); + output = null; + } + if (tempFile.exists()) + tempFile.delete(); + } + + /** + * Clears and resets the cache. + */ + public void reset() throws IOException { + if (output != null) { + output.close(); + output = null; + } + if (tempFile.exists()) + tempFile.delete(); + } +} diff --git a/src/org/apache/fop/tools/AreaTreeBuilder.java b/src/org/apache/fop/tools/AreaTreeBuilder.java index 89888d434..cb5eb4a20 100644 --- a/src/org/apache/fop/tools/AreaTreeBuilder.java +++ b/src/org/apache/fop/tools/AreaTreeBuilder.java @@ -117,7 +117,7 @@ public class AreaTreeBuilder { PageViewport page = sm.getPage(count, c); c++; // save the page to a stream for testing - ObjectOutputStream tempstream = new ObjectOutputStream( + /*ObjectOutputStream tempstream = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream("temp.ser"))); page.savePage(tempstream); @@ -129,7 +129,7 @@ public class AreaTreeBuilder { new BufferedInputStream( new FileInputStream("temp.ser"))); page.loadPage(in); - in.close(); + in.close();*/ rend.renderPage(page); } @@ -331,6 +331,7 @@ class TreeLoader { reg.addBlock(obj); } } + reg.setCTM(new CTM()); return reg; } diff --git a/src/org/apache/fop/util/StreamUtilities.java b/src/org/apache/fop/util/StreamUtilities.java new file mode 100644 index 000000000..418d656e0 --- /dev/null +++ b/src/org/apache/fop/util/StreamUtilities.java @@ -0,0 +1,147 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ +package org.apache.fop.util; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.EOFException; +import java.io.DataInput; +import java.io.DataOutput; +import java.util.zip.CRC32; + +/** + * General handy stream i/o methods. + */ +public class StreamUtilities { + + /** + * Size of buffers. Duh. + */ + public static final int BUFFER_SIZE = 4096; // cuz I like big buffers... + + /** + * Binary copies bytes from an input stream to an output stream. + * The process is buffered, so you shouldn't need + * BufferedInput/OutputStreams. Flushes when it's finished, but does + * not close either stream. Returns the number of bytes copied. + */ + public static long streamCopy(InputStream source, + OutputStream sink) throws IOException { + // set table + byte[] buffer = new byte[BUFFER_SIZE]; + long total = 0; + + // trough + int scoop; + while ((scoop = source.read(buffer)) >= 0) { + if (scoop == 0) + System.out.println("zero scoop!"); + sink.write(buffer, 0, scoop); + total += scoop; + } + + // do dishes + sink.flush(); + + return total; + } + + /** + * Binary copies up to the given number of bytes from an input + * stream to an output stream. The process is buffered, so you + * shouldn't need BufferedInput/OutputStreams. + * Flushes when it's finished, but does not close either stream. + * Throws an EOFExeption if there aren't enough bytes available to + * transfer the requested amount. + * Returns the total number of bytes copied. + */ + public static long streamCopy(InputStream source, + OutputStream sink, int howMany) throws IOException { + // set table + byte[] buffer = new byte[BUFFER_SIZE]; + int left = howMany; + + // trough + int scoop; + while (left > 0) { + scoop = source.read(buffer, 0, Math.min(BUFFER_SIZE, left)); + if (scoop < 0) + throw new EOFException( + "Not enough bytes to feed you in IOLib.streamCopy(source, sink, howMany); you asked for " + + howMany + " and I only have " + (howMany - left)); + + sink.write(buffer, 0, scoop); + left -= scoop; + } + + // do dishes + sink.flush(); + + return howMany; + } + + /** + * Binary copies up to the given number of bytes from an input + * stream to an output stream. The process is buffered, so you + * shouldn't need BufferedInput/OutputStreams. + * Flushes when it's finished, but does not close either stream. + * Throws an EOFExeption if there aren't enough bytes available + * to transfer the requested amount. + * Returns the checksum of the bytes copied. + */ + public static long streamCopyWithChecksum(InputStream source, + OutputStream sink, int howMany) throws IOException { + // set table + byte[] buffer = new byte[BUFFER_SIZE]; + int left = howMany; + CRC32 checksummer = new CRC32(); + + // trough + int scoop; + while (left > 0) { + scoop = source.read(buffer, 0, Math.min(BUFFER_SIZE, left)); + if (scoop < 0) + throw new EOFException("Not enough bytes to feed you in IOLib.streamCopy(source, sink, howMany)"); + + checksummer.update(buffer, 0, scoop); + sink.write(buffer, 0, scoop); + left -= scoop; + } + + // do dishes + sink.flush(); + + return checksummer.getValue(); + } + + /** + * Binary copies up to the given number of bytes from a DataInput + * object to an DataOutput object. The process is buffered. Since + * DataOutput doesn't support closing or flushing, it does neither. + * Returns the total number of bytes copied. + */ + public static long dataCopy(DataInput source, DataOutput sink, + int howMany) throws IOException { + // set table + byte[] buffer = new byte[BUFFER_SIZE]; + int left = howMany; + + // trough + int scoop; + while (left > 0) { + scoop = Math.min(BUFFER_SIZE, left); + source.readFully(buffer, 0, scoop); + sink.write(buffer, 0, scoop); + left -= scoop; + } + + // do dishes + return howMany; + } + +} |