package freenet.support;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import freenet.client.async.ClientContext;
import freenet.support.api.Bucket;
import freenet.support.api.LockableRandomAccessBuffer;
import freenet.support.api.RandomAccessBucket;
import freenet.support.io.ByteArrayRandomAccessBuffer;
/**
* Simple read-only array bucket. Just an adapter class to save some RAM.
* Wraps a byte[], offset, length into a Bucket. Read-only. ArrayBucket on
* the other hand is a chain of byte[]'s.
*
* Not serializable as it doesn't copy. Should only be used for short-lived hacks for that reason.
*/
public class SimpleReadOnlyArrayBucket implements Bucket, RandomAccessBucket {
private static final long serialVersionUID = 1L;
final byte[] buf;
final int offset;
final int length;
public SimpleReadOnlyArrayBucket(byte[] buf, int offset, int length) {
this.buf = buf;
this.offset = offset;
this.length = length;
}
public SimpleReadOnlyArrayBucket(byte[] buf) {
this(buf, 0, buf.length);
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new IOException("Read only");
}
@Override
public OutputStream getOutputStreamUnbuffered() throws IOException {
throw new IOException("Read only");
}
@Override
public InputStream getInputStreamUnbuffered() throws IOException {
return new ByteArrayInputStream(buf, offset, length);
}
@Override
public InputStream getInputStream() throws IOException {
return getInputStreamUnbuffered();
}
@Override
public String getName() {
return "SimpleReadOnlyArrayBucket: len="+length+ ' ' +super.toString();
}
@Override
public long size() {
return length;
}
@Override
public boolean isReadOnly() {
return true;
}
@Override
public void setReadOnly() {
// Already read-only
}
@Override
public void free() {
// Do nothing
}
@Override
public RandomAccessBucket createShadow() {
if(buf.length < 256*1024) {
return new SimpleReadOnlyArrayBucket(Arrays.copyOfRange(buf, offset, offset+length));
}
return null;
}
@Override
public void onResume(ClientContext context) {
// Not persistent.
throw new UnsupportedOperationException();
}
@Override
public void storeTo(DataOutputStream dos) {
// Not persistent.
throw new UnsupportedOperationException();
}
@Override
public LockableRandomAccessBuffer toRandomAccessBuffer() throws IOException {
ByteArrayRandomAccessBuffer raf = new ByteArrayRandomAccessBuffer(buf, offset, length, true);
raf.setReadOnly();
return raf;
}
}