aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/java/org/apache/poi/poifs/filesystem/POIFSStream.java406
1 files changed, 203 insertions, 203 deletions
diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSStream.java b/src/java/org/apache/poi/poifs/filesystem/POIFSStream.java
index 8d8f7c575d..d1b83afc04 100644
--- a/src/java/org/apache/poi/poifs/filesystem/POIFSStream.java
+++ b/src/java/org/apache/poi/poifs/filesystem/POIFSStream.java
@@ -32,155 +32,155 @@ import org.apache.poi.poifs.storage.HeaderBlock;
/**
* This handles reading and writing a stream within a
- * {@link POIFSFileSystem}. It can supply an iterator
- * to read blocks, and way to write out to existing and
- * new blocks.
+ * {@link POIFSFileSystem}. It can supply an iterator
+ * to read blocks, and way to write out to existing and
+ * new blocks.
* Most users will want a higher level version of this,
- * which deals with properties to track which stream
- * this is.
+ * which deals with properties to track which stream
+ * this is.
* This only works on big block streams, it doesn't
- * handle small block ones.
+ * handle small block ones.
* This uses the new NIO code
- *
+ * <p>
* TODO Implement a streaming write method, and append
*/
-public class POIFSStream implements Iterable<ByteBuffer>
-{
- private final BlockStore blockStore;
- private int startBlock;
- private OutputStream outStream;
-
- /**
- * Constructor for an existing stream. It's up to you
- * to know how to get the start block (eg from a
- * {@link HeaderBlock} or a {@link Property})
- */
- public POIFSStream(BlockStore blockStore, int startBlock) {
- this.blockStore = blockStore;
- this.startBlock = startBlock;
- }
-
- /**
- * Constructor for a new stream. A start block won't
- * be allocated until you begin writing to it.
- */
- public POIFSStream(BlockStore blockStore) {
- this.blockStore = blockStore;
- this.startBlock = POIFSConstants.END_OF_CHAIN;
- }
-
- /**
- * What block does this stream start at?
- * Will be {@link POIFSConstants#END_OF_CHAIN} for a
- * new stream that hasn't been written to yet.
- */
- public int getStartBlock() {
- return startBlock;
- }
-
- /**
- * Returns an iterator that'll supply one {@link ByteBuffer}
- * per block in the stream.
- */
- public Iterator<ByteBuffer> iterator() {
- return getBlockIterator();
- }
-
- Iterator<ByteBuffer> getBlockIterator() {
- if(startBlock == POIFSConstants.END_OF_CHAIN) {
- throw new IllegalStateException(
- "Can't read from a new stream before it has been written to"
- );
- }
- return new StreamBlockByteBufferIterator(startBlock);
- }
-
- Iterator<Integer> getBlockOffsetIterator() {
- if(startBlock == POIFSConstants.END_OF_CHAIN) {
- throw new IllegalStateException(
- "Can't read from a new stream before it has been written to"
- );
- }
- return new StreamBlockOffsetIterator(startBlock);
- }
-
- /**
- * Updates the contents of the stream to the new
- * set of bytes.
- * Note - if this is property based, you'll still
- * need to update the size in the property yourself
- */
- void updateContents(byte[] contents) throws IOException {
- OutputStream os = getOutputStream();
- os.write(contents);
- os.close();
- }
-
- public OutputStream getOutputStream() throws IOException {
- if (outStream == null) {
- outStream = new StreamBlockByteBuffer();
- }
- return outStream;
- }
-
- // TODO Streaming write support
- // TODO then convert fixed sized write to use streaming internally
- // TODO Append write support (probably streaming)
-
- /**
- * Frees all blocks in the stream
- */
- public void free() throws IOException {
- ChainLoopDetector loopDetector = blockStore.getChainLoopDetector();
- free(loopDetector);
- }
- private void free(ChainLoopDetector loopDetector) {
- int nextBlock = startBlock;
- while(nextBlock != POIFSConstants.END_OF_CHAIN) {
- int thisBlock = nextBlock;
- loopDetector.claim(thisBlock);
- nextBlock = blockStore.getNextBlock(thisBlock);
- blockStore.setNextBlock(thisBlock, POIFSConstants.UNUSED_BLOCK);
- }
- this.startBlock = POIFSConstants.END_OF_CHAIN;
- }
-
- /**
- * Class that handles a streaming read of one stream
- */
- private class StreamBlockOffsetIterator implements Iterator<Integer> {
- private final ChainLoopDetector loopDetector;
- private int nextBlock;
-
- StreamBlockOffsetIterator(int firstBlock) {
- this.nextBlock = firstBlock;
- try {
- this.loopDetector = blockStore.getChainLoopDetector();
- } catch(IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- public boolean hasNext() {
- return nextBlock != POIFSConstants.END_OF_CHAIN;
- }
-
- public Integer next() {
- if (!hasNext()) {
- throw new NoSuchElementException("Can't read past the end of the stream");
- }
-
- loopDetector.claim(nextBlock);
- int currentBlock = nextBlock;
- nextBlock = blockStore.getNextBlock(nextBlock);
- return currentBlock;
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
+public class POIFSStream implements Iterable<ByteBuffer> {
+ private final BlockStore blockStore;
+ private int startBlock;
+ private OutputStream outStream;
+
+ /**
+ * Constructor for an existing stream. It's up to you
+ * to know how to get the start block (eg from a
+ * {@link HeaderBlock} or a {@link Property})
+ */
+ public POIFSStream(BlockStore blockStore, int startBlock) {
+ this.blockStore = blockStore;
+ this.startBlock = startBlock;
+ }
+
+ /**
+ * Constructor for a new stream. A start block won't
+ * be allocated until you begin writing to it.
+ */
+ public POIFSStream(BlockStore blockStore) {
+ this.blockStore = blockStore;
+ this.startBlock = POIFSConstants.END_OF_CHAIN;
+ }
+
+ /**
+ * What block does this stream start at?
+ * Will be {@link POIFSConstants#END_OF_CHAIN} for a
+ * new stream that hasn't been written to yet.
+ */
+ public int getStartBlock() {
+ return startBlock;
+ }
+
+ /**
+ * Returns an iterator that'll supply one {@link ByteBuffer}
+ * per block in the stream.
+ */
+ public Iterator<ByteBuffer> iterator() {
+ return getBlockIterator();
+ }
+
+ Iterator<ByteBuffer> getBlockIterator() {
+ if (startBlock == POIFSConstants.END_OF_CHAIN) {
+ throw new IllegalStateException(
+ "Can't read from a new stream before it has been written to"
+ );
+ }
+ return new StreamBlockByteBufferIterator(startBlock);
+ }
+
+ Iterator<Integer> getBlockOffsetIterator() {
+ if (startBlock == POIFSConstants.END_OF_CHAIN) {
+ throw new IllegalStateException(
+ "Can't read from a new stream before it has been written to"
+ );
+ }
+ return new StreamBlockOffsetIterator(startBlock);
+ }
+
+ /**
+ * Updates the contents of the stream to the new
+ * set of bytes.
+ * Note - if this is property based, you'll still
+ * need to update the size in the property yourself
+ */
+ void updateContents(byte[] contents) throws IOException {
+ OutputStream os = getOutputStream();
+ os.write(contents);
+ os.close();
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ if (outStream == null) {
+ outStream = new StreamBlockByteBuffer();
+ }
+ return outStream;
+ }
+
+ // TODO Streaming write support
+ // TODO then convert fixed sized write to use streaming internally
+ // TODO Append write support (probably streaming)
+
+ /**
+ * Frees all blocks in the stream
+ */
+ public void free() throws IOException {
+ ChainLoopDetector loopDetector = blockStore.getChainLoopDetector();
+ free(loopDetector);
+ }
+
+ private void free(ChainLoopDetector loopDetector) {
+ int nextBlock = startBlock;
+ while (nextBlock != POIFSConstants.END_OF_CHAIN) {
+ int thisBlock = nextBlock;
+ loopDetector.claim(thisBlock);
+ nextBlock = blockStore.getNextBlock(thisBlock);
+ blockStore.setNextBlock(thisBlock, POIFSConstants.UNUSED_BLOCK);
+ }
+ this.startBlock = POIFSConstants.END_OF_CHAIN;
+ }
+
+ /**
+ * Class that handles a streaming read of one stream
+ */
+ private class StreamBlockOffsetIterator implements Iterator<Integer> {
+ private final ChainLoopDetector loopDetector;
+ private int nextBlock;
+
+ StreamBlockOffsetIterator(int firstBlock) {
+ this.nextBlock = firstBlock;
+ try {
+ this.loopDetector = blockStore.getChainLoopDetector();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean hasNext() {
+ return nextBlock != POIFSConstants.END_OF_CHAIN;
+ }
+
+ public Integer next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException("Can't read past the end of the stream");
+ }
+
+ loopDetector.claim(nextBlock);
+ int currentBlock = nextBlock;
+ nextBlock = blockStore.getNextBlock(nextBlock);
+ return currentBlock;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
/**
* Class that handles a streaming read of one stream
@@ -203,7 +203,7 @@ public class POIFSStream implements Iterable<ByteBuffer>
try {
return blockStore.getBlockAt(offsetIterator.next());
- } catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException(e);
}
}
@@ -214,66 +214,66 @@ public class POIFSStream implements Iterable<ByteBuffer>
}
- protected class StreamBlockByteBuffer extends OutputStream {
- byte[] oneByte = new byte[1];
- ByteBuffer buffer;
- // Make sure we don't encounter a loop whilst overwriting
- // the existing blocks
- ChainLoopDetector loopDetector;
- int prevBlock, nextBlock;
-
- StreamBlockByteBuffer() throws IOException {
- loopDetector = blockStore.getChainLoopDetector();
- prevBlock = POIFSConstants.END_OF_CHAIN;
- nextBlock = startBlock;
- }
-
- void createBlockIfNeeded() throws IOException {
- if (buffer != null && buffer.hasRemaining()) return;
-
- int thisBlock = nextBlock;
-
- // Allocate a block if needed, otherwise figure
- // out what the next block will be
- if(thisBlock == POIFSConstants.END_OF_CHAIN) {
- thisBlock = blockStore.getFreeBlock();
- loopDetector.claim(thisBlock);
-
- // We're on the end of the chain
- nextBlock = POIFSConstants.END_OF_CHAIN;
-
- // Mark the previous block as carrying on to us if needed
- if(prevBlock != POIFSConstants.END_OF_CHAIN) {
- blockStore.setNextBlock(prevBlock, thisBlock);
- }
- blockStore.setNextBlock(thisBlock, POIFSConstants.END_OF_CHAIN);
-
- // If we've just written the first block on a
- // new stream, save the start block offset
- if(startBlock == POIFSConstants.END_OF_CHAIN) {
- startBlock = thisBlock;
- }
- } else {
- loopDetector.claim(thisBlock);
- nextBlock = blockStore.getNextBlock(thisBlock);
- }
-
- if (buffer != null) {
- blockStore.releaseBuffer(buffer);
- }
- buffer = blockStore.createBlockIfNeeded(thisBlock);
-
- // Update pointers
- prevBlock = thisBlock;
- }
-
- @Override
- public void write(int b) throws IOException {
- oneByte[0] = (byte)(b & 0xFF);
+ protected class StreamBlockByteBuffer extends OutputStream {
+ byte[] oneByte = new byte[1];
+ ByteBuffer buffer;
+ // Make sure we don't encounter a loop whilst overwriting
+ // the existing blocks
+ ChainLoopDetector loopDetector;
+ int prevBlock, nextBlock;
+
+ StreamBlockByteBuffer() throws IOException {
+ loopDetector = blockStore.getChainLoopDetector();
+ prevBlock = POIFSConstants.END_OF_CHAIN;
+ nextBlock = startBlock;
+ }
+
+ void createBlockIfNeeded() throws IOException {
+ if (buffer != null && buffer.hasRemaining()) return;
+
+ int thisBlock = nextBlock;
+
+ // Allocate a block if needed, otherwise figure
+ // out what the next block will be
+ if (thisBlock == POIFSConstants.END_OF_CHAIN) {
+ thisBlock = blockStore.getFreeBlock();
+ loopDetector.claim(thisBlock);
+
+ // We're on the end of the chain
+ nextBlock = POIFSConstants.END_OF_CHAIN;
+
+ // Mark the previous block as carrying on to us if needed
+ if (prevBlock != POIFSConstants.END_OF_CHAIN) {
+ blockStore.setNextBlock(prevBlock, thisBlock);
+ }
+ blockStore.setNextBlock(thisBlock, POIFSConstants.END_OF_CHAIN);
+
+ // If we've just written the first block on a
+ // new stream, save the start block offset
+ if (startBlock == POIFSConstants.END_OF_CHAIN) {
+ startBlock = thisBlock;
+ }
+ } else {
+ loopDetector.claim(thisBlock);
+ nextBlock = blockStore.getNextBlock(thisBlock);
+ }
+
+ if (buffer != null) {
+ blockStore.releaseBuffer(buffer);
+ }
+ buffer = blockStore.createBlockIfNeeded(thisBlock);
+
+ // Update pointers
+ prevBlock = thisBlock;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ oneByte[0] = (byte) (b & 0xFF);
write(oneByte);
- }
+ }
- @Override
+ @Override
public void write(byte[] b, int off, int len) throws IOException {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
@@ -301,6 +301,6 @@ public class POIFSStream implements Iterable<ByteBuffer>
blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN);
}
}
- }
+ }
}