670 lines
20 KiB
Java
670 lines
20 KiB
Java
|
|
||
|
/* ====================================================================
|
||
|
* The Apache Software License, Version 1.1
|
||
|
*
|
||
|
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||
|
* reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
*
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
*
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in
|
||
|
* the documentation and/or other materials provided with the
|
||
|
* distribution.
|
||
|
*
|
||
|
* 3. The end-user documentation included with the redistribution,
|
||
|
* if any, must include the following acknowledgment:
|
||
|
* "This product includes software developed by the
|
||
|
* Apache Software Foundation (http://www.apache.org/)."
|
||
|
* Alternately, this acknowledgment may appear in the software itself,
|
||
|
* if and wherever such third-party acknowledgments normally appear.
|
||
|
*
|
||
|
* 4. The names "Apache" and "Apache Software Foundation" and
|
||
|
* "Apache POI" must not be used to endorse or promote products
|
||
|
* derived from this software without prior written permission. For
|
||
|
* written permission, please contact apache@apache.org.
|
||
|
*
|
||
|
* 5. Products derived from this software may not be called "Apache",
|
||
|
* "Apache POI", nor may "Apache" appear in their name, without
|
||
|
* prior written permission of the Apache Software Foundation.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
* ====================================================================
|
||
|
*
|
||
|
* This software consists of voluntary contributions made by many
|
||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||
|
* information on the Apache Software Foundation, please see
|
||
|
* <http://www.apache.org/>.
|
||
|
*/
|
||
|
|
||
|
package org.apache.poi.poifs.filesystem;
|
||
|
|
||
|
import java.io.*;
|
||
|
|
||
|
import java.util.*;
|
||
|
|
||
|
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.RawDataBlock;
|
||
|
import org.apache.poi.poifs.storage.SmallDocumentBlock;
|
||
|
import org.apache.poi.util.HexDump;
|
||
|
|
||
|
/**
|
||
|
* This class manages a document in the POIFS filesystem.
|
||
|
*
|
||
|
* @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 = "<NO DATA>";
|
||
|
}
|
||
|
}
|
||
|
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
|
||
|
|