DeepCopy.java
package ac.essex.ooechs.imaging.commons.util;
import java.io.*;
/**
* Utility for making deep copies (vs. clone()'s shallow copies) of
* objects. Objects are first serialized and then deserialized. Error
* checking is fairly minimal in this implementation. If an object is
* encountered that cannot be serialized (or that references an object
* that cannot be serialized) an error is printed to System.err and
* null is returned. Depending on your specific application, it might
* make more sense to have copy(...) re-throw the exception.
*/
public class DeepCopy {
/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*/
public Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
FastByteArrayOutputStream fbos = new FastByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(fbos);
out.writeObject(orig);
out.flush();
out.close();
// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(fbos.getInputStream());
obj = in.readObject();
} catch (IOException e) {
e.printStackTrace();
}
catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
class FastByteArrayInputStream extends InputStream {
/*
* Our byte buffer
*/
protected byte[] buf = null;
/*
* Number of bytes that we can read from the buffer
*/
protected int count = 0;
/*
* Number of bytes that have been read from the buffer
*/
protected int pos = 0;
public FastByteArrayInputStream(byte[] buf, int count) {
this.buf = buf;
this.count = count;
}
public final int available() {
return count - pos;
}
public final int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
public final int read(byte[] b, int off, int len) {
if (pos >= count)
return -1;
if ((pos + len) > count)
len = (count - pos);
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public final long skip(long n) {
if ((pos + n) > count)
n = count - pos;
if (n < 0)
return 0;
pos += n;
return n;
}
}
class FastByteArrayOutputStream extends OutputStream {
/**
* Buffer and size
*/
protected byte[] buf = null;
protected int size = 0;
/**
* Constructs a stream with buffer capacity size 5K
*/
public FastByteArrayOutputStream() {
this(5 * 1024);
}
/**
* Constructs a stream with the given initial size
*/
public FastByteArrayOutputStream(int initSize) {
this.size = 0;
this.buf = new byte[initSize];
}
/**
* Ensures that we have a large enough buffer for the given size.
*/
private void verifyBufferSize(int sz) {
if (sz > buf.length) {
byte[] old = buf;
buf = new byte[Math.max(sz, 2 * buf.length)];
System.arraycopy(old, 0, buf, 0, old.length);
old = null;
}
}
public int getSize() {
return size;
}
/**
* Returns the byte array containing the written data. Note that this
* array will almost always be larger than the amount of data actually
* written.
*/
public byte[] getByteArray() {
return buf;
}
public final void write(byte b[]) {
verifyBufferSize(size + b.length);
System.arraycopy(b, 0, buf, size, b.length);
size += b.length;
}
public final void write(byte b[], int off, int len) {
verifyBufferSize(size + len);
System.arraycopy(b, off, buf, size, len);
size += len;
}
public final void write(int b) {
verifyBufferSize(size + 1);
buf[size++] = (byte) b;
}
public void reset() {
size = 0;
}
/**
* Returns a ByteArrayInputStream for reading back the written data
*/
public InputStream getInputStream() {
return new FastByteArrayInputStream(buf, size);
}
}
}