diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java index c313baf489..772d3e9d94 100644 --- a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -15,21 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - package org.apache.poi.poifs.filesystem; -import java.io.*; - -import java.util.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.dev.POIFSViewable; import org.apache.poi.poifs.property.DocumentProperty; import org.apache.poi.poifs.property.Property; import org.apache.poi.poifs.storage.BlockWritable; -import org.apache.poi.poifs.storage.ListManagedBlock; import org.apache.poi.poifs.storage.DocumentBlock; +import org.apache.poi.poifs.storage.ListManagedBlock; import org.apache.poi.poifs.storage.RawDataBlock; import org.apache.poi.poifs.storage.SmallDocumentBlock; import org.apache.poi.util.HexDump; @@ -39,595 +42,438 @@ import org.apache.poi.util.HexDump; * * @author Marc Johnson (mjohnson at apache dot org) */ - -public class POIFSDocument - implements BATManaged, BlockWritable, POIFSViewable -{ - private DocumentProperty _property; - private int _size; - - // one of these stores will be valid - private SmallBlockStore _small_store; - private BigBlockStore _big_store; - - /** - * Constructor from large blocks - * - * @param name the name of the POIFSDocument - * @param blocks the big blocks making up the POIFSDocument - * @param length the actual length of the POIFSDocument - * - * @exception IOException - */ - - public POIFSDocument(final String name, final RawDataBlock [] blocks, - final int length) - throws IOException - { - _size = length; - _big_store = new BigBlockStore(blocks); - _property = new DocumentProperty(name, _size); - _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); - _property.setDocument(this); - } - - /** - * Constructor from small blocks - * - * @param name the name of the POIFSDocument - * @param blocks the small blocks making up the POIFSDocument - * @param length the actual length of the POIFSDocument - */ - - public POIFSDocument(final String name, - final SmallDocumentBlock [] blocks, final int length) - { - _size = length; - try - { - _big_store = new BigBlockStore(new RawDataBlock[ 0 ]); - } - catch (IOException ignored) - { - - // can't happen with that constructor - } - _property = new DocumentProperty(name, _size); - _small_store = new SmallBlockStore(blocks); - _property.setDocument(this); - } - - /** - * Constructor from small blocks - * - * @param name the name of the POIFSDocument - * @param blocks the small blocks making up the POIFSDocument - * @param length the actual length of the POIFSDocument - * - * @exception IOException - */ - - public POIFSDocument(final String name, final ListManagedBlock [] blocks, - final int length) - throws IOException - { - _size = length; - _property = new DocumentProperty(name, _size); - _property.setDocument(this); - if (Property.isSmall(_size)) - { - _big_store = new BigBlockStore(new RawDataBlock[ 0 ]); - _small_store = new SmallBlockStore(blocks); - } - else - { - _big_store = new BigBlockStore(blocks); - _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); - } - } - - /** - * Constructor - * - * @param name the name of the POIFSDocument - * @param stream the InputStream we read data from - * - * @exception IOException thrown on read errors - */ - - public POIFSDocument(final String name, final InputStream stream) - throws IOException - { - List blocks = new ArrayList(); - - _size = 0; - while (true) - { - DocumentBlock block = new DocumentBlock(stream); - int blockSize = block.size(); - - if (blockSize > 0) - { - blocks.add(block); - _size += blockSize; - } - if (block.partiallyRead()) - { - break; - } - } - DocumentBlock[] bigBlocks = - ( DocumentBlock [] ) blocks.toArray(new DocumentBlock[ 0 ]); - - _big_store = new BigBlockStore(bigBlocks); - _property = new DocumentProperty(name, _size); - _property.setDocument(this); - if (_property.shouldUseSmallBlocks()) - { - _small_store = - new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks, - _size)); - _big_store = new BigBlockStore(new DocumentBlock[ 0 ]); - } - else - { - _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); - } - } - - /** - * Constructor - * - * @param name the name of the POIFSDocument - * @param size the length of the POIFSDocument - * @param path the path of the POIFSDocument - * @param writer the writer who will eventually write the document - * contents - * - * @exception IOException thrown on read errors - */ - - public POIFSDocument(final String name, final int size, - final POIFSDocumentPath path, - final POIFSWriterListener writer) - throws IOException - { - _size = size; - _property = new DocumentProperty(name, _size); - _property.setDocument(this); - if (_property.shouldUseSmallBlocks()) - { - _small_store = new SmallBlockStore(path, name, size, writer); - _big_store = new BigBlockStore(new Object[ 0 ]); - } - else - { - _small_store = new SmallBlockStore(new BlockWritable[ 0 ]); - _big_store = new BigBlockStore(path, name, size, writer); - } - } - - /** - * return the array of SmallDocumentBlocks used - * - * @return array of SmallDocumentBlocks; may be empty, cannot be null - */ - - public BlockWritable [] getSmallBlocks() - { - return _small_store.getBlocks(); - } - - /** - * @return size of the document - */ - - public int getSize() - { - return _size; - } - - /** - * read data from the internal stores - * - * @param buffer the buffer to write to - * @param offset the offset into our storage to read from - */ - - void read(final byte [] buffer, final int offset) - { - if (_property.shouldUseSmallBlocks()) - { - SmallDocumentBlock.read(_small_store.getBlocks(), buffer, offset); - } - else - { - DocumentBlock.read(_big_store.getBlocks(), buffer, offset); - } - } - - /** - * Get the DocumentProperty - * - * @return the instance's DocumentProperty - */ - - DocumentProperty getDocumentProperty() - { - return _property; - } - - /* ********** START implementation of BlockWritable ********** */ - - /** - * Write the storage to an OutputStream - * - * @param stream the OutputStream to which the stored data should - * be written - * - * @exception IOException on problems writing to the specified - * stream - */ - - public void writeBlocks(final OutputStream stream) - throws IOException - { - _big_store.writeBlocks(stream); - } - - /* ********** END implementation of BlockWritable ********** */ - /* ********** START implementation of BATManaged ********** */ - - /** - * Return the number of BigBlock's this instance uses - * - * @return count of BigBlock instances - */ - - public int countBlocks() - { - return _big_store.countBlocks(); - } - - /** - * Set the start block for this instance - * - * @param index index into the array of blocks making up the - * filesystem - */ - - public void setStartBlock(final int index) - { - _property.setStartBlock(index); - } - - /* ********** END implementation of BATManaged ********** */ - /* ********** START begin implementation of POIFSViewable ********** */ - - /** - * Get an array of objects, some of which may implement - * POIFSViewable - * - * @return an array of Object; may not be null, but may be empty - */ - - public Object [] getViewableArray() - { - Object[] results = new Object[ 1 ]; - String result; - - try - { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - BlockWritable[] blocks = null; - - if (_big_store.isValid()) - { - blocks = _big_store.getBlocks(); - } - else if (_small_store.isValid()) - { - blocks = _small_store.getBlocks(); - } - if (blocks != null) - { - for (int k = 0; k < blocks.length; k++) - { - blocks[ k ].writeBlocks(output); - } - byte[] data = output.toByteArray(); - - if (data.length > _property.getSize()) - { - byte[] tmp = new byte[ _property.getSize() ]; - - System.arraycopy(data, 0, tmp, 0, tmp.length); - data = tmp; - } - output = new ByteArrayOutputStream(); - HexDump.dump(data, 0, output, 0); - result = output.toString(); - } - else - { - result = ""; - } - } - catch (IOException e) - { - result = e.getMessage(); - } - results[ 0 ] = result; - return results; - } - - /** - * Get an Iterator of objects, some of which may implement - * POIFSViewable - * - * @return an Iterator; may not be null, but may have an empty - * back end store - */ - - public Iterator getViewableIterator() - { - return Collections.EMPTY_LIST.iterator(); - } - - /** - * Give viewers a hint as to whether to call getViewableArray or - * getViewableIterator - * - * @return true if a viewer should call getViewableArray, false if - * a viewer should call getViewableIterator - */ - - public boolean preferArray() - { - return true; - } - - /** - * Provides a short description of the object, to be used when a - * POIFSViewable object has not provided its contents. - * - * @return short description - */ - - public String getShortDescription() - { - StringBuffer buffer = new StringBuffer(); - - buffer.append("Document: \"").append(_property.getName()) - .append("\""); - buffer.append(" size = ").append(getSize()); - return buffer.toString(); - } - - /* ********** END begin implementation of POIFSViewable ********** */ - private class SmallBlockStore - { - private SmallDocumentBlock[] smallBlocks; - private POIFSDocumentPath path; - private String name; - private int size; - private POIFSWriterListener writer; - - /** - * Constructor - * - * @param blocks blocks to construct the store from - */ - - SmallBlockStore(final Object [] blocks) - { - smallBlocks = new SmallDocumentBlock[ blocks.length ]; - for (int j = 0; j < blocks.length; j++) - { - smallBlocks[ j ] = ( SmallDocumentBlock ) blocks[ j ]; - } - this.path = null; - this.name = null; - this.size = -1; - this.writer = null; - } - - /** - * Constructor for a small block store that will be written - * later - * - * @param path path of the document - * @param name name of the document - * @param size length of the document - * @param writer the object that will eventually write the document - */ - - SmallBlockStore(final POIFSDocumentPath path, final String name, - final int size, final POIFSWriterListener writer) - { - smallBlocks = new SmallDocumentBlock[ 0 ]; - this.path = path; - this.name = name; - this.size = size; - this.writer = writer; - } - - /** - * @return true if this store is a valid source of data - */ - - boolean isValid() - { - return ((smallBlocks.length > 0) || (writer != null)); - } - - /** - * @return the SmallDocumentBlocks - */ - - BlockWritable [] getBlocks() - { - if (isValid() && (writer != null)) - { - ByteArrayOutputStream stream = - new ByteArrayOutputStream(size); - DocumentOutputStream dstream = - new DocumentOutputStream(stream, size); - - writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, - path, name, size)); - smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(), - size); - } - return smallBlocks; - } - } // end private class SmallBlockStore - - private class BigBlockStore - { - private DocumentBlock[] bigBlocks; - private POIFSDocumentPath path; - private String name; - private int size; - private POIFSWriterListener writer; - - /** - * Constructor - * - * @param blocks the blocks making up the store - * - * @exception IOException on I/O error - */ - - BigBlockStore(final Object [] blocks) - throws IOException - { - bigBlocks = new DocumentBlock[ blocks.length ]; - for (int j = 0; j < blocks.length; j++) - { - if (blocks[ j ] instanceof DocumentBlock) - { - bigBlocks[ j ] = ( DocumentBlock ) blocks[ j ]; - } - else - { - bigBlocks[ j ] = - new DocumentBlock(( RawDataBlock ) blocks[ j ]); - } - } - this.path = null; - this.name = null; - this.size = -1; - this.writer = null; - } - - /** - * Constructor for a big block store that will be written - * later - * - * @param path path of the document - * @param name name of the document - * @param size length of the document - * @param writer the object that will eventually write the - * document - */ - - BigBlockStore(final POIFSDocumentPath path, final String name, - final int size, final POIFSWriterListener writer) - { - bigBlocks = new DocumentBlock[ 0 ]; - this.path = path; - this.name = name; - this.size = size; - this.writer = writer; - } - - /** - * @return true if this store is a valid source of data - */ - - boolean isValid() - { - return ((bigBlocks.length > 0) || (writer != null)); - } - - /** - * @return the DocumentBlocks - */ - - DocumentBlock [] getBlocks() - { - if (isValid() && (writer != null)) - { - ByteArrayOutputStream stream = - new ByteArrayOutputStream(size); - DocumentOutputStream dstream = - new DocumentOutputStream(stream, size); - - writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, - path, name, size)); - bigBlocks = DocumentBlock.convert(stream.toByteArray(), size); - } - return bigBlocks; - } - - /** - * write the blocks to a stream - * - * @param stream the stream to which the data is to be written - * - * @exception IOException on error - */ - - void writeBlocks(OutputStream stream) - throws IOException - { - if (isValid()) - { - if (writer != null) - { - DocumentOutputStream dstream = - new DocumentOutputStream(stream, size); - - writer.processPOIFSWriterEvent( - new POIFSWriterEvent(dstream, path, name, size)); - dstream.writeFiller(countBlocks() - * POIFSConstants - .BIG_BLOCK_SIZE, DocumentBlock - .getFillByte()); - } - else - { - for (int k = 0; k < bigBlocks.length; k++) - { - bigBlocks[ k ].writeBlocks(stream); - } - } - } - } - - /** - * @return number of big blocks making up this document - */ - - int countBlocks() - { - int rval = 0; - - if (isValid()) - { - if (writer != null) - { - rval = (size + POIFSConstants.BIG_BLOCK_SIZE - 1) - / POIFSConstants.BIG_BLOCK_SIZE; - } - else - { - rval = bigBlocks.length; - } - } - return rval; - } - } // end private class BigBlockStore -} // end class POIFSDocument - +public final class POIFSDocument implements BATManaged, BlockWritable, POIFSViewable { + private static final DocumentBlock[] EMPTY_BIG_BLOCK_ARRAY = { }; + private static final SmallDocumentBlock[] EMPTY_SMALL_BLOCK_ARRAY = { }; + private DocumentProperty _property; + private int _size; + + // one of these stores will be valid + private SmallBlockStore _small_store; + private BigBlockStore _big_store; + + /** + * Constructor from large blocks + * + * @param name the name of the POIFSDocument + * @param blocks the big blocks making up the POIFSDocument + * @param length the actual length of the POIFSDocument + */ + public POIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException { + _size = length; + _big_store = new BigBlockStore(convertRawBlocksToBigBlocks(blocks)); + _property = new DocumentProperty(name, _size); + _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY); + _property.setDocument(this); + } + + // TODO - awkward typing going on here + private static DocumentBlock[] convertRawBlocksToBigBlocks(ListManagedBlock[] blocks) throws IOException { + DocumentBlock[] result = new DocumentBlock[blocks.length]; + for (int i = 0; i < result.length; i++) { + result[i] = new DocumentBlock((RawDataBlock)blocks[i]); + } + return result; + } + private static SmallDocumentBlock[] convertRawBlocksToSmallBlocks(ListManagedBlock[] blocks) { + if (blocks instanceof SmallDocumentBlock[]) { + return (SmallDocumentBlock[]) blocks; + } + SmallDocumentBlock[] result = new SmallDocumentBlock[blocks.length]; + System.arraycopy(blocks, 0, result, 0, blocks.length); + return result; + } + + /** + * Constructor from small blocks + * + * @param name the name of the POIFSDocument + * @param blocks the small blocks making up the POIFSDocument + * @param length the actual length of the POIFSDocument + */ + public POIFSDocument(String name, SmallDocumentBlock[] blocks, int length) { + _size = length; + _big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY); + _property = new DocumentProperty(name, _size); + _small_store = new SmallBlockStore(blocks); + _property.setDocument(this); + } + + /** + * Constructor from small blocks + * + * @param name the name of the POIFSDocument + * @param blocks the small blocks making up the POIFSDocument + * @param length the actual length of the POIFSDocument + */ + public POIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException { + _size = length; + _property = new DocumentProperty(name, _size); + _property.setDocument(this); + if (Property.isSmall(_size)) { + _big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY); + _small_store = new SmallBlockStore(convertRawBlocksToSmallBlocks(blocks)); + } else { + _big_store = new BigBlockStore(convertRawBlocksToBigBlocks(blocks)); + _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY); + } + } + + /** + * Constructor + * + * @param name the name of the POIFSDocument + * @param stream the InputStream we read data from + */ + public POIFSDocument(String name, InputStream stream) throws IOException { + List blocks = new ArrayList(); + + _size = 0; + while (true) { + DocumentBlock block = new DocumentBlock(stream); + int blockSize = block.size(); + + if (blockSize > 0) { + blocks.add(block); + _size += blockSize; + } + if (block.partiallyRead()) { + break; + } + } + DocumentBlock[] bigBlocks = (DocumentBlock[]) blocks.toArray(new DocumentBlock[blocks.size()]); + + _big_store = new BigBlockStore(bigBlocks); + _property = new DocumentProperty(name, _size); + _property.setDocument(this); + if (_property.shouldUseSmallBlocks()) { + _small_store = new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks, _size)); + _big_store = new BigBlockStore(new DocumentBlock[0]); + } else { + _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY); + } + } + + /** + * Constructor + * + * @param name the name of the POIFSDocument + * @param size the length of the POIFSDocument + * @param path the path of the POIFSDocument + * @param writer the writer who will eventually write the document contents + */ + public POIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) { + _size = size; + _property = new DocumentProperty(name, _size); + _property.setDocument(this); + if (_property.shouldUseSmallBlocks()) { + _small_store = new SmallBlockStore(path, name, size, writer); + _big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY); + } else { + _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY); + _big_store = new BigBlockStore(path, name, size, writer); + } + } + + /** + * @return array of SmallDocumentBlocks; may be empty, cannot be null + */ + public BlockWritable[] getSmallBlocks() { + return _small_store.getBlocks(); + } + + /** + * @return size of the document + */ + public int getSize() { + return _size; + } + + /** + * read data from the internal stores + * + * @param buffer the buffer to write to + * @param offset the offset into our storage to read from + */ + void read(byte[] buffer, int offset) { + if (_property.shouldUseSmallBlocks()) { + SmallDocumentBlock.read(_small_store.getBlocks(), buffer, offset); + } else { + DocumentBlock.read(_big_store.getBlocks(), buffer, offset); + } + } + + /** + * @return the instance's DocumentProperty + */ + + DocumentProperty getDocumentProperty() { + return _property; + } + + /* ********** START implementation of BlockWritable ********** */ + + /** + * Write the storage to an OutputStream + * + * @param stream the OutputStream to which the stored data should be written + */ + public void writeBlocks(OutputStream stream) throws IOException { + _big_store.writeBlocks(stream); + } + + /* ********** END implementation of BlockWritable ********** */ + /* ********** START implementation of BATManaged ********** */ + + /** + * Return the number of BigBlock's this instance uses + * + * @return count of BigBlock instances + */ + public int countBlocks() { + return _big_store.countBlocks(); + } + + /** + * Set the start block for this instance + * + * @param index index into the array of blocks making up the filesystem + */ + public void setStartBlock(int index) { + _property.setStartBlock(index); + } + + /* ********** END implementation of BATManaged ********** */ + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + public Object[] getViewableArray() { + Object[] results = new Object[1]; + String result; + + try { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + BlockWritable[] blocks = null; + + if (_big_store.isValid()) { + blocks = _big_store.getBlocks(); + } else if (_small_store.isValid()) { + blocks = _small_store.getBlocks(); + } + if (blocks != null) { + for (int k = 0; k < blocks.length; k++) { + blocks[k].writeBlocks(output); + } + byte[] data = output.toByteArray(); + + if (data.length > _property.getSize()) { + byte[] tmp = new byte[_property.getSize()]; + + System.arraycopy(data, 0, tmp, 0, tmp.length); + data = tmp; + } + output = new ByteArrayOutputStream(); + HexDump.dump(data, 0, output, 0); + result = output.toString(); + } else { + result = ""; + } + } catch (IOException e) { + result = e.getMessage(); + } + results[0] = result; + return results; + } + + /** + * Get an Iterator of objects, some of which may implement POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty back end + * store + */ + public Iterator getViewableIterator() { + return Collections.EMPTY_LIST.iterator(); + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, + * false if a viewer should call getViewableIterator + */ + public boolean preferArray() { + return true; + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + public String getShortDescription() { + StringBuffer buffer = new StringBuffer(); + + buffer.append("Document: \"").append(_property.getName()).append("\""); + buffer.append(" size = ").append(getSize()); + return buffer.toString(); + } + + /* ********** END begin implementation of POIFSViewable ********** */ + private static final class SmallBlockStore { + private SmallDocumentBlock[] smallBlocks; + private final POIFSDocumentPath path; + private final String name; + private final int size; + private final POIFSWriterListener writer; + + /** + * Constructor + * + * @param blocks blocks to construct the store from + */ + SmallBlockStore(SmallDocumentBlock[] blocks) { + smallBlocks = (SmallDocumentBlock[]) blocks.clone(); + this.path = null; + this.name = null; + this.size = -1; + this.writer = null; + } + + /** + * Constructor for a small block store that will be written later + * + * @param path path of the document + * @param name name of the document + * @param size length of the document + * @param writer the object that will eventually write the document + */ + SmallBlockStore(POIFSDocumentPath path, String name, int size, POIFSWriterListener writer) { + smallBlocks = new SmallDocumentBlock[0]; + this.path = path; + this.name = name; + this.size = size; + this.writer = writer; + } + + /** + * @return true if this store is a valid source of data + */ + boolean isValid() { + return smallBlocks.length > 0 || writer != null; + } + + /** + * @return the SmallDocumentBlocks + */ + SmallDocumentBlock[] getBlocks() { + if (isValid() && writer != null) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(size); + DocumentOutputStream dstream = new DocumentOutputStream(stream, size); + + writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, path, name, size)); + smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(), size); + } + return smallBlocks; + } + } // end private class SmallBlockStore + + private static final class BigBlockStore { + private DocumentBlock[] bigBlocks; + private final POIFSDocumentPath path; + private final String name; + private final int size; + private final POIFSWriterListener writer; + + /** + * Constructor + * + * @param blocks the blocks making up the store + */ + BigBlockStore(DocumentBlock[] blocks) { + bigBlocks = (DocumentBlock[]) blocks.clone(); + this.path = null; + this.name = null; + this.size = -1; + this.writer = null; + } + + /** + * Constructor for a big block store that will be written later + * + * @param path path of the document + * @param name name of the document + * @param size length of the document + * @param writer the object that will eventually write the document + */ + BigBlockStore(POIFSDocumentPath path, String name, int size, POIFSWriterListener writer) { + bigBlocks = new DocumentBlock[0]; + this.path = path; + this.name = name; + this.size = size; + this.writer = writer; + } + + /** + * @return true if this store is a valid source of data + */ + boolean isValid() { + return bigBlocks.length > 0 || writer != null; + } + + /** + * @return the DocumentBlocks + */ + DocumentBlock[] getBlocks() { + if (isValid() && writer != null) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(size); + DocumentOutputStream dstream = new DocumentOutputStream(stream, size); + + writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, path, name, size)); + bigBlocks = DocumentBlock.convert(stream.toByteArray(), size); + } + return bigBlocks; + } + + /** + * write the blocks to a stream + * + * @param stream the stream to which the data is to be written + */ + void writeBlocks(OutputStream stream) throws IOException { + if (isValid()) { + if (writer != null) { + DocumentOutputStream dstream = new DocumentOutputStream(stream, size); + + writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, path, name, size)); + dstream.writeFiller(countBlocks() * POIFSConstants.BIG_BLOCK_SIZE, + DocumentBlock.getFillByte()); + } else { + for (int k = 0; k < bigBlocks.length; k++) { + bigBlocks[k].writeBlocks(stream); + } + } + } + } + + /** + * @return number of big blocks making up this document + */ + int countBlocks() { + + if (isValid()) { + if (writer == null) { + return bigBlocks.length; + } + return (size + POIFSConstants.BIG_BLOCK_SIZE - 1) + / POIFSConstants.BIG_BLOCK_SIZE; + } + return 0; + } + } // end private class BigBlockStore +}