package test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; public class SerializableInputStream extends InputStream implements Serializable { /** * */ private static final long serialVersionUID = 0L; private InputStream stream; /** * Creates a new serializable stream. A client must not use any of the * available methods on this input stream if he wishes to serialize this * stream, otherwise the passed stream is only serialized partially! * * @param stream the stream to serialize. */ public SerializableInputStream(InputStream stream) { this.stream = stream; } //--------------------------< InputStream >--------------------------------- /** * Forwards the call to the underlying stream. */ public int read() throws IOException { return stream.read(); } /** * Forwards the call to the underlying stream. */ public int available() throws IOException { return stream.available(); } /** * Forwards the call to the underlying stream. */ public void close() throws IOException { stream.close(); } /** * Forwards the call to the underlying stream. */ public void reset() throws IOException { stream.reset(); } /** * Forwards the call to the underlying stream. */ public boolean markSupported() { return stream.markSupported(); } /** * Forwards the call to the underlying stream. */ public void mark(int readlimit) { stream.mark(readlimit); } /** * Forwards the call to the underlying stream. */ public long skip(long n) throws IOException { return stream.skip(n); } /** * Forwards the call to the underlying stream. */ public int read(byte b[]) throws IOException { return stream.read(b); } /** * Forwards the call to the underlying stream. */ public int read(byte b[], int off, int len) throws IOException { return stream.read(b, off, len); } //---------------------------< Serializable >------------------------------- /** * Writes the contents of the underlying stream to the * ObjectOutputStream. * * @param out The ObjectOutputStream to where the binary data * is copied. * @throws IOException If an error occurs writing the binary data. */ private void writeObject(ObjectOutputStream out) throws IOException { byte[] buffer = new byte[4096]; int bytes; while ((bytes = stream.read(buffer)) >= 0) { // Write a segment of the input stream if (bytes > 0) { // just to ensure that no 0 is written out.writeInt(bytes); out.write(buffer, 0, bytes); } } // Write the end of stream marker out.writeInt(0); // close stream stream.close(); } /** * Reads the binary data from the ObjectInputStream into a * temporary file that is used to back up the binary stream contents of the * constructed value instance. The temporary file gets deleted when the * binary stream is closed or garbage collected. * * @param in The ObjectInputStream from where to get the binary * data. * @throws IOException If an error occurs reading the binary data. */ private void readObject(ObjectInputStream in) throws IOException { final File file = File.createTempFile("serializable-stream", "bin"); OutputStream out = new FileOutputStream(file); byte[] buffer = new byte[4096]; for (int bytes = in.readInt(); bytes > 0; bytes = in.readInt()) { if (buffer.length < bytes) { buffer = new byte[bytes]; } in.readFully(buffer, 0, bytes); out.write(buffer, 0, bytes); } out.close(); stream = new FileInputStream(file) { private boolean closed = false; public void close() throws IOException { super.close(); closed = true; file.delete(); } protected void finalize() throws IOException { try { if (!closed) { file.delete(); } } finally { super.finalize(); } } }; } }