You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ni...@apache.org on 2010/12/30 03:35:11 UTC
svn commit: r1053791 [6/18] - in /poi/branches/NIO_32_BRANCH: ./
src/contrib/src/org/apache/poi/contrib/poibrowser/ src/java/org/apache/poi/
src/java/org/apache/poi/hpsf/ src/java/org/apache/poi/hpsf/extractor/
src/java/org/apache/poi/hssf/record/ src/...
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/BlockListImpl.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/BlockListImpl.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/BlockListImpl.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/BlockListImpl.java Thu Dec 30 02:35:06 2010
@@ -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,30 +14,20 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
-import java.io.*;
-
-import java.util.*;
+import java.io.IOException;
/**
* A simple implementation of BlockList
*
* @author Marc Johnson (mjohnson at apache dot org
*/
-
-class BlockListImpl
- implements BlockList
-{
+abstract class BlockListImpl implements BlockList {
private ListManagedBlock[] _blocks;
private BlockAllocationTableReader _bat;
- /**
- * Constructor BlockListImpl
- */
-
protected BlockListImpl()
{
_blocks = new ListManagedBlock[ 0 ];
@@ -50,21 +39,17 @@ class BlockListImpl
*
* @param blocks blocks to be managed
*/
-
protected void setBlocks(final ListManagedBlock [] blocks)
{
_blocks = blocks;
}
- /* ********** START implementation of BlockList ********** */
-
/**
* remove the specified block from the list
*
* @param index the index of the specified block; if the index is
* out of range, that's ok
*/
-
public void zap(final int index)
{
if ((index >= 0) && (index < _blocks.length))
@@ -74,6 +59,14 @@ class BlockListImpl
}
/**
+ * Unit testing method. Gets, without sanity checks or
+ * removing.
+ */
+ protected ListManagedBlock get(final int index) {
+ return _blocks[index];
+ }
+
+ /**
* remove and return the specified block from the list
*
* @param index the index of the specified block
@@ -83,7 +76,6 @@ class BlockListImpl
* @exception IOException if the index is out of range or has
* already been removed
*/
-
public ListManagedBlock remove(final int index)
throws IOException
{
@@ -94,15 +86,17 @@ class BlockListImpl
result = _blocks[ index ];
if (result == null)
{
- throw new IOException("block[ " + index
- + " ] already removed");
+ throw new IOException(
+ "block[ " + index + " ] already removed - " +
+ "does your POIFS have circular or duplicate block references?"
+ );
}
_blocks[ index ] = null;
}
catch (ArrayIndexOutOfBoundsException ignored)
{
throw new IOException("Cannot remove block[ " + index
- + " ]; out of range[ 0 - " +
+ + " ]; out of range[ 0 - " +
(_blocks.length-1) + " ]");
}
return result;
@@ -118,8 +112,7 @@ class BlockListImpl
*
* @exception IOException if blocks are missing
*/
-
- public ListManagedBlock [] fetchBlocks(final int startBlock)
+ public ListManagedBlock [] fetchBlocks(final int startBlock, final int headerPropertiesStartBlock)
throws IOException
{
if (_bat == null)
@@ -127,17 +120,14 @@ class BlockListImpl
throw new IOException(
"Improperly initialized list: no block allocation table provided");
}
- return _bat.fetchBlocks(startBlock, this);
+ return _bat.fetchBlocks(startBlock, headerPropertiesStartBlock, this);
}
/**
* set the associated BlockAllocationTable
*
* @param bat the associated BlockAllocationTable
- *
- * @exception IOException
*/
-
public void setBAT(final BlockAllocationTableReader bat)
throws IOException
{
@@ -148,7 +138,21 @@ class BlockListImpl
}
_bat = bat;
}
-
- /* ********** END implementation of BlockList ********** */
-} // end package-scope class BlockListImpl
-
+
+ /**
+ * Returns the count of the number of blocks
+ */
+ public int blockCount() {
+ return _blocks.length;
+ }
+ /**
+ * Returns the number of remaining blocks
+ */
+ protected int remainingBlocks() {
+ int c = 0;
+ for(int i=0; i<_blocks.length; i++) {
+ if(_blocks[i] != null) c++;
+ }
+ return c;
+ }
+}
Added: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DataInputBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DataInputBlock.java?rev=1053791&view=auto
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DataInputBlock.java (added)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DataInputBlock.java Thu Dec 30 02:35:06 2010
@@ -0,0 +1,186 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.poifs.storage;
+
+/**
+ * Wraps a <tt>byte</tt> array and provides simple data input access.
+ * Internally, this class maintains a buffer read index, so that for the most part, primitive
+ * data can be read in a data-input-stream-like manner.<p/>
+ *
+ * Note - the calling class should call the {@link #available()} method to detect end-of-buffer
+ * and move to the next data block when the current is exhausted.
+ * For optimisation reasons, no error handling is performed in this class. Thus, mistakes in
+ * calling code ran may raise ugly exceptions here, like {@link ArrayIndexOutOfBoundsException},
+ * etc .<p/>
+ *
+ * The multi-byte primitive input methods ({@link #readUShortLE()}, {@link #readIntLE()} and
+ * {@link #readLongLE()}) have corresponding 'spanning read' methods which (when required) perform
+ * a read across the block boundary. These spanning read methods take the previous
+ * {@link DataInputBlock} as a parameter.
+ * Reads of larger amounts of data (into <tt>byte</tt> array buffers) must be managed by the caller
+ * since these could conceivably involve more than two blocks.
+ *
+ * @author Josh Micich
+ */
+public final class DataInputBlock {
+
+ /**
+ * Possibly any size (usually 512K or 64K). Assumed to be at least 8 bytes for all blocks
+ * before the end of the stream. The last block in the stream can be any size except zero.
+ */
+ private final byte[] _buf;
+ private int _readIndex;
+ private int _maxIndex;
+
+ DataInputBlock(byte[] data, int startOffset) {
+ _buf = data;
+ _readIndex = startOffset;
+ _maxIndex = _buf.length;
+ }
+ public int available() {
+ return _maxIndex-_readIndex;
+ }
+
+ public int readUByte() {
+ return _buf[_readIndex++] & 0xFF;
+ }
+
+ /**
+ * Reads a <tt>short</tt> which was encoded in <em>little endian</em> format.
+ */
+ public int readUShortLE() {
+ int i = _readIndex;
+
+ int b0 = _buf[i++] & 0xFF;
+ int b1 = _buf[i++] & 0xFF;
+ _readIndex = i;
+ return (b1 << 8) + (b0 << 0);
+ }
+
+ /**
+ * Reads a <tt>short</tt> which spans the end of <tt>prevBlock</tt> and the start of this block.
+ */
+ public int readUShortLE(DataInputBlock prevBlock) {
+ // simple case - will always be one byte in each block
+ int i = prevBlock._buf.length-1;
+
+ int b0 = prevBlock._buf[i++] & 0xFF;
+ int b1 = _buf[_readIndex++] & 0xFF;
+ return (b1 << 8) + (b0 << 0);
+ }
+
+ /**
+ * Reads an <tt>int</tt> which was encoded in <em>little endian</em> format.
+ */
+ public int readIntLE() {
+ int i = _readIndex;
+
+ int b0 = _buf[i++] & 0xFF;
+ int b1 = _buf[i++] & 0xFF;
+ int b2 = _buf[i++] & 0xFF;
+ int b3 = _buf[i++] & 0xFF;
+ _readIndex = i;
+ return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
+ }
+
+ /**
+ * Reads an <tt>int</tt> which spans the end of <tt>prevBlock</tt> and the start of this block.
+ */
+ public int readIntLE(DataInputBlock prevBlock, int prevBlockAvailable) {
+ byte[] buf = new byte[4];
+
+ readSpanning(prevBlock, prevBlockAvailable, buf);
+ int b0 = buf[0] & 0xFF;
+ int b1 = buf[1] & 0xFF;
+ int b2 = buf[2] & 0xFF;
+ int b3 = buf[3] & 0xFF;
+ return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
+ }
+
+ /**
+ * Reads a <tt>long</tt> which was encoded in <em>little endian</em> format.
+ */
+ public long readLongLE() {
+ int i = _readIndex;
+
+ int b0 = _buf[i++] & 0xFF;
+ int b1 = _buf[i++] & 0xFF;
+ int b2 = _buf[i++] & 0xFF;
+ int b3 = _buf[i++] & 0xFF;
+ int b4 = _buf[i++] & 0xFF;
+ int b5 = _buf[i++] & 0xFF;
+ int b6 = _buf[i++] & 0xFF;
+ int b7 = _buf[i++] & 0xFF;
+ _readIndex = i;
+ return (((long)b7 << 56) +
+ ((long)b6 << 48) +
+ ((long)b5 << 40) +
+ ((long)b4 << 32) +
+ ((long)b3 << 24) +
+ (b2 << 16) +
+ (b1 << 8) +
+ (b0 << 0));
+ }
+
+ /**
+ * Reads a <tt>long</tt> which spans the end of <tt>prevBlock</tt> and the start of this block.
+ */
+ public long readLongLE(DataInputBlock prevBlock, int prevBlockAvailable) {
+ byte[] buf = new byte[8];
+
+ readSpanning(prevBlock, prevBlockAvailable, buf);
+
+ int b0 = buf[0] & 0xFF;
+ int b1 = buf[1] & 0xFF;
+ int b2 = buf[2] & 0xFF;
+ int b3 = buf[3] & 0xFF;
+ int b4 = buf[4] & 0xFF;
+ int b5 = buf[5] & 0xFF;
+ int b6 = buf[6] & 0xFF;
+ int b7 = buf[7] & 0xFF;
+ return (((long)b7 << 56) +
+ ((long)b6 << 48) +
+ ((long)b5 << 40) +
+ ((long)b4 << 32) +
+ ((long)b3 << 24) +
+ (b2 << 16) +
+ (b1 << 8) +
+ (b0 << 0));
+ }
+
+ /**
+ * Reads a small amount of data from across the boundary between two blocks.
+ * The {@link #_readIndex} of this (the second) block is updated accordingly.
+ * Note- this method (and other code) assumes that the second {@link DataInputBlock}
+ * always is big enough to complete the read without being exhausted.
+ */
+ private void readSpanning(DataInputBlock prevBlock, int prevBlockAvailable, byte[] buf) {
+ System.arraycopy(prevBlock._buf, prevBlock._readIndex, buf, 0, prevBlockAvailable);
+ int secondReadLen = buf.length-prevBlockAvailable;
+ System.arraycopy(_buf, 0, buf, prevBlockAvailable, secondReadLen);
+ _readIndex = secondReadLen;
+ }
+
+ /**
+ * Reads <tt>len</tt> bytes from this block into the supplied buffer.
+ */
+ public void readFully(byte[] buf, int off, int len) {
+ System.arraycopy(_buf, _readIndex, buf, off, len);
+ _readIndex += len;
+ }
+}
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DocumentBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DocumentBlock.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DocumentBlock.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/DocumentBlock.java Thu Dec 30 02:35:06 2010
@@ -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,31 +14,24 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-
import java.util.Arrays;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.IntegerField;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.LittleEndianConsts;
/**
* A block of document data.
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
-public class DocumentBlock
- extends BigBlock
-{
+public final class DocumentBlock extends BigBlock {
private static final byte _default_value = ( byte ) 0xFF;
private byte[] _data;
private int _bytes_read;
@@ -55,6 +47,11 @@ public class DocumentBlock
public DocumentBlock(final RawDataBlock block)
throws IOException
{
+ super(
+ block.getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE ?
+ POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS :
+ POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS
+ );
_data = block.getData();
_bytes_read = _data.length;
}
@@ -67,10 +64,10 @@ public class DocumentBlock
* @exception IOException
*/
- public DocumentBlock(final InputStream stream)
+ public DocumentBlock(final InputStream stream, POIFSBigBlockSize bigBlockSize)
throws IOException
{
- this();
+ this(bigBlockSize);
int count = IOUtils.readFully(stream, _data);
_bytes_read = (count == -1) ? 0
@@ -81,9 +78,10 @@ public class DocumentBlock
* Create a single instance initialized with default values
*/
- private DocumentBlock()
+ private DocumentBlock(POIFSBigBlockSize bigBlockSize)
{
- _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
+ super(bigBlockSize);
+ _data = new byte[ bigBlockSize.getBigBlockSize() ];
Arrays.fill(_data, _default_value);
}
@@ -106,7 +104,7 @@ public class DocumentBlock
public boolean partiallyRead()
{
- return _bytes_read != POIFSConstants.BIG_BLOCK_SIZE;
+ return _bytes_read != bigBlockSize.getBigBlockSize();
}
/**
@@ -129,26 +127,27 @@ public class DocumentBlock
* input array
*/
- public static DocumentBlock [] convert(final byte [] array,
+ public static DocumentBlock [] convert(final POIFSBigBlockSize bigBlockSize,
+ final byte [] array,
final int size)
{
DocumentBlock[] rval =
- new DocumentBlock[ (size + POIFSConstants.BIG_BLOCK_SIZE - 1) / POIFSConstants.BIG_BLOCK_SIZE ];
+ new DocumentBlock[ (size + bigBlockSize.getBigBlockSize() - 1) / bigBlockSize.getBigBlockSize() ];
int offset = 0;
for (int k = 0; k < rval.length; k++)
{
- rval[ k ] = new DocumentBlock();
+ rval[ k ] = new DocumentBlock(bigBlockSize);
if (offset < array.length)
{
- int length = Math.min(POIFSConstants.BIG_BLOCK_SIZE,
+ int length = Math.min(bigBlockSize.getBigBlockSize(),
array.length - offset);
System.arraycopy(array, offset, rval[ k ]._data, 0, length);
- if (length != POIFSConstants.BIG_BLOCK_SIZE)
+ if (length != bigBlockSize.getBigBlockSize())
{
Arrays.fill(rval[ k ]._data, length,
- POIFSConstants.BIG_BLOCK_SIZE,
+ bigBlockSize.getBigBlockSize(),
_default_value);
}
}
@@ -156,50 +155,26 @@ public class DocumentBlock
{
Arrays.fill(rval[ k ]._data, _default_value);
}
- offset += POIFSConstants.BIG_BLOCK_SIZE;
+ offset += bigBlockSize.getBigBlockSize();
}
return rval;
}
- /**
- * read data from an array of DocumentBlocks
- *
- * @param blocks the blocks to read from
- * @param buffer the buffer to write the data into
- * @param offset the offset into the array of blocks to read from
- */
-
- public static void read(final DocumentBlock [] blocks,
- final byte [] buffer, final int offset)
- {
- int firstBlockIndex = offset / POIFSConstants.BIG_BLOCK_SIZE;
- int firstBlockOffset = offset % POIFSConstants.BIG_BLOCK_SIZE;
- int lastBlockIndex = (offset + buffer.length - 1)
- / POIFSConstants.BIG_BLOCK_SIZE;
-
- if (firstBlockIndex == lastBlockIndex)
- {
- System.arraycopy(blocks[ firstBlockIndex ]._data,
- firstBlockOffset, buffer, 0, buffer.length);
- }
- else
- {
- int buffer_offset = 0;
-
- System.arraycopy(blocks[ firstBlockIndex ]._data,
- firstBlockOffset, buffer, buffer_offset,
- POIFSConstants.BIG_BLOCK_SIZE
- - firstBlockOffset);
- buffer_offset += POIFSConstants.BIG_BLOCK_SIZE - firstBlockOffset;
- for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++)
- {
- System.arraycopy(blocks[ j ]._data, 0, buffer, buffer_offset,
- POIFSConstants.BIG_BLOCK_SIZE);
- buffer_offset += POIFSConstants.BIG_BLOCK_SIZE;
- }
- System.arraycopy(blocks[ lastBlockIndex ]._data, 0, buffer,
- buffer_offset, buffer.length - buffer_offset);
+ public static DataInputBlock getDataInputBlock(DocumentBlock[] blocks, int offset) {
+ if(blocks == null || blocks.length == 0) {
+ return null;
}
+
+ // Key things about the size of the block
+ POIFSBigBlockSize bigBlockSize = blocks[0].bigBlockSize;
+ int BLOCK_SHIFT = bigBlockSize.getHeaderValue();
+ int BLOCK_SIZE = bigBlockSize.getBigBlockSize();
+ int BLOCK_MASK = BLOCK_SIZE - 1;
+
+ // Now do the offset lookup
+ int firstBlockIndex = offset >> BLOCK_SHIFT;
+ int firstBlockOffset= offset & BLOCK_MASK;
+ return new DataInputBlock(blocks[firstBlockIndex]._data, firstBlockOffset);
}
/* ********** START extension of BigBlock ********** */
Added: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlock.java?rev=1053791&view=auto
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlock.java (added)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlock.java Thu Dec 30 02:35:06 2010
@@ -0,0 +1,388 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.poifs.storage;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
+import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.IntegerField;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LongField;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.ShortField;
+
+/**
+ * The block containing the archive header
+ */
+public final class HeaderBlock implements HeaderBlockConstants {
+ private static final POILogger _logger =
+ POILogFactory.getLogger(HeaderBlock.class);
+
+ /**
+ * What big block size the file uses. Most files
+ * use 512 bytes, but a few use 4096
+ */
+ private final POIFSBigBlockSize bigBlockSize;
+
+ /**
+ * Number of big block allocation table blocks (int).
+ * (Number of FAT Sectors in Microsoft parlance).
+ */
+ private int _bat_count;
+
+ /**
+ * Start of the property set block (int index of the property set
+ * chain's first big block).
+ */
+ private int _property_start;
+
+ /**
+ * start of the small block allocation table (int index of small
+ * block allocation table's first big block)
+ */
+ private int _sbat_start;
+ /**
+ * Number of small block allocation table blocks (int)
+ * (Number of MiniFAT Sectors in Microsoft parlance)
+ */
+ private int _sbat_count;
+
+ /**
+ * Big block index for extension to the big block allocation table
+ */
+ private int _xbat_start;
+ /**
+ * Number of big block allocation table blocks (int)
+ * (Number of DIFAT Sectors in Microsoft parlance)
+ */
+ private int _xbat_count;
+
+ /**
+ * The data. Only ever 512 bytes, because 4096 byte
+ * files use zeros for the extra header space.
+ */
+ private final byte[] _data;
+
+ private static final byte _default_value = ( byte ) 0xFF;
+
+ /**
+ * create a new HeaderBlockReader from an InputStream
+ *
+ * @param stream the source InputStream
+ *
+ * @exception IOException on errors or bad data
+ */
+ public HeaderBlock(InputStream stream) throws IOException {
+ // Grab the first 512 bytes
+ // (For 4096 sized blocks, the remaining 3584 bytes are zero)
+ // Then, process the contents
+ this(readFirst512(stream));
+
+ // Fetch the rest of the block if needed
+ if(bigBlockSize.getBigBlockSize() != 512) {
+ int rest = bigBlockSize.getBigBlockSize() - 512;
+ byte[] tmp = new byte[rest];
+ IOUtils.readFully(stream, tmp);
+ }
+ }
+
+ public HeaderBlock(ByteBuffer buffer) throws IOException {
+ this(IOUtils.toByteArray(buffer, POIFSConstants.SMALLER_BIG_BLOCK_SIZE));
+ }
+
+ private HeaderBlock(byte[] data) throws IOException {
+ this._data = data;
+
+ // verify signature
+ long signature = LittleEndian.getLong(_data, _signature_offset);
+
+ if (signature != _signature) {
+ // Is it one of the usual suspects?
+ byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
+ if(_data[0] == OOXML_FILE_HEADER[0] &&
+ _data[1] == OOXML_FILE_HEADER[1] &&
+ _data[2] == OOXML_FILE_HEADER[2] &&
+ _data[3] == OOXML_FILE_HEADER[3]) {
+ throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)");
+ }
+ if ((signature & 0xFF8FFFFFFFFFFFFFL) == 0x0010000200040009L) {
+ // BIFF2 raw stream starts with BOF (sid=0x0009, size=0x0004, data=0x00t0)
+ throw new IllegalArgumentException("The supplied data appears to be in BIFF2 format. "
+ + "POI only supports BIFF8 format");
+ }
+
+ // Give a generic error
+ throw new IOException("Invalid header signature; read "
+ + longToHex(signature) + ", expected "
+ + longToHex(_signature));
+ }
+
+
+ // Figure out our block size
+ if (_data[30] == 12) {
+ this.bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS;
+ } else if(_data[30] == 9) {
+ this.bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
+ } else {
+ throw new IOException("Unsupported blocksize (2^"+ _data[30] + "). Expected 2^9 or 2^12.");
+ }
+
+ // Setup the fields to read and write the counts and starts
+ _bat_count = new IntegerField(_bat_count_offset, data).get();
+ _property_start = new IntegerField(_property_start_offset,_data).get();
+ _sbat_start = new IntegerField(_sbat_start_offset, _data).get();
+ _sbat_count = new IntegerField(_sbat_block_count_offset, _data).get();
+ _xbat_start = new IntegerField(_xbat_start_offset, _data).get();
+ _xbat_count = new IntegerField(_xbat_count_offset, _data).get();
+ }
+
+ /**
+ * Create a single instance initialized with default values
+ */
+ public HeaderBlock(POIFSBigBlockSize bigBlockSize)
+ {
+ this.bigBlockSize = bigBlockSize;
+
+ // Our data is always 512 big no matter what
+ _data = new byte[ POIFSConstants.SMALLER_BIG_BLOCK_SIZE ];
+ Arrays.fill(_data, _default_value);
+
+ // Set all the default values
+ new LongField(_signature_offset, _signature, _data);
+ new IntegerField(0x08, 0, _data);
+ new IntegerField(0x0c, 0, _data);
+ new IntegerField(0x10, 0, _data);
+ new IntegerField(0x14, 0, _data);
+ new ShortField(0x18, ( short ) 0x3b, _data);
+ new ShortField(0x1a, ( short ) 0x3, _data);
+ new ShortField(0x1c, ( short ) -2, _data);
+
+ new ShortField(0x1e, bigBlockSize.getHeaderValue(), _data);
+ new IntegerField(0x20, 0x6, _data);
+ new IntegerField(0x24, 0, _data);
+ new IntegerField(0x28, 0, _data);
+ new IntegerField(0x34, 0, _data);
+ new IntegerField(0x38, 0x1000, _data);
+
+ // Initialise the variables
+ _bat_count = 0;
+ _sbat_count = 0;
+ _xbat_count = 0;
+ _property_start = POIFSConstants.END_OF_CHAIN;
+ _sbat_start = POIFSConstants.END_OF_CHAIN;
+ _xbat_start = POIFSConstants.END_OF_CHAIN;
+ }
+
+ private static byte[] readFirst512(InputStream stream) throws IOException {
+ // Grab the first 512 bytes
+ // (For 4096 sized blocks, the remaining 3584 bytes are zero)
+ byte[] data = new byte[512];
+ int bsCount = IOUtils.readFully(stream, data);
+ if(bsCount != 512) {
+ throw alertShortRead(bsCount, 512);
+ }
+ return data;
+ }
+
+ private static String longToHex(long value) {
+ return new String(HexDump.longToHex(value));
+ }
+
+ private static IOException alertShortRead(int pRead, int expectedReadSize) {
+ int read;
+ if (pRead < 0) {
+ //Can't have -1 bytes read in the error message!
+ read = 0;
+ } else {
+ read = pRead;
+ }
+ String type = " byte" + (read == 1 ? (""): ("s"));
+
+ return new IOException("Unable to read entire header; "
+ + read + type + " read; expected "
+ + expectedReadSize + " bytes");
+ }
+
+ /**
+ * get start of Property Table
+ *
+ * @return the index of the first block of the Property Table
+ */
+ public int getPropertyStart() {
+ return _property_start;
+ }
+ /**
+ * Set start of Property Table
+ *
+ * @param startBlock the index of the first block of the Property Table
+ */
+ public void setPropertyStart(final int startBlock) {
+ _property_start = startBlock;
+ }
+
+ /**
+ * @return start of small block (MiniFAT) allocation table
+ */
+ public int getSBATStart() {
+ return _sbat_start;
+ }
+ public int getSBATCount() {
+ return _sbat_count;
+ }
+
+ /**
+ * Set start of small block allocation table
+ *
+ * @param startBlock the index of the first big block of the small
+ * block allocation table
+ */
+ public void setSBATStart(final int startBlock) {
+ _sbat_start = startBlock;
+ }
+ /**
+ * Set count of SBAT blocks
+ *
+ * @param count the number of SBAT blocks
+ */
+ public void setSBATBlockCount(final int count)
+ {
+ _sbat_count = count;
+ }
+
+ /**
+ * @return number of BAT blocks
+ */
+ public int getBATCount() {
+ return _bat_count;
+ }
+ /**
+ * Sets the number of BAT blocks that are used.
+ * This is the number used in both the BAT and XBAT.
+ */
+ public void setBATCount(final int count) {
+ _bat_count = count;
+ }
+
+ /**
+ * Returns the offsets to the first (up to) 109
+ * BAT sectors.
+ * Any additional BAT sectors are held in the XBAT (DIFAT)
+ * sectors in a chain.
+ * @return BAT offset array
+ */
+ public int[] getBATArray() {
+ // Read them in
+ int[] result = new int[ Math.min(_bat_count,_max_bats_in_header) ];
+ int offset = _bat_array_offset;
+ for (int j = 0; j < result.length; j++) {
+ result[ j ] = LittleEndian.getInt(_data, offset);
+ offset += LittleEndianConsts.INT_SIZE;
+ }
+ return result;
+ }
+ /**
+ * Sets the offsets of the first (up to) 109
+ * BAT sectors.
+ */
+ public void setBATArray(int[] bat_array) {
+ int count = Math.min(bat_array.length, _max_bats_in_header);
+ int blank = _max_bats_in_header - count;
+
+ int offset = _bat_array_offset;
+ for(int i=0; i<count; i++) {
+ LittleEndian.putInt(_data, offset, bat_array[i]);
+ offset += LittleEndianConsts.INT_SIZE;
+ }
+ for(int i=0; i<blank; i++) {
+ LittleEndian.putInt(_data, offset, POIFSConstants.UNUSED_BLOCK);
+ offset += LittleEndianConsts.INT_SIZE;
+ }
+ }
+
+ /**
+ * @return XBAT (DIFAT) count
+ */
+ public int getXBATCount() {
+ return _xbat_count;
+ }
+ /**
+ * Sets the number of XBAT (DIFAT) blocks used
+ */
+ public void setXBATCount(final int count) {
+ _xbat_count = count;
+ }
+
+ /**
+ * @return XBAT (DIFAT) index
+ */
+ public int getXBATIndex() {
+ return _xbat_start;
+ }
+ /**
+ * Sets the first XBAT (DIFAT) block location
+ */
+ public void setXBATStart(final int startBlock) {
+ _xbat_start = startBlock;
+ }
+
+ /**
+ * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+ */
+ public POIFSBigBlockSize getBigBlockSize() {
+ return bigBlockSize;
+ }
+
+ /**
+ * Write the block's data to an OutputStream
+ *
+ * @param stream the OutputStream to which the stored data should
+ * be written
+ *
+ * @exception IOException on problems writing to the specified
+ * stream
+ */
+ void writeData(final OutputStream stream)
+ throws IOException
+ {
+ // Update the counts and start positions
+ new IntegerField(_bat_count_offset, _bat_count, _data);
+ new IntegerField(_property_start_offset, _property_start, _data);
+ new IntegerField(_sbat_start_offset, _sbat_start, _data);
+ new IntegerField(_sbat_block_count_offset, _sbat_count, _data);
+ new IntegerField(_xbat_start_offset, _xbat_start, _data);
+ new IntegerField(_xbat_count_offset, _xbat_count, _data);
+
+ // Write the main data out
+ stream.write(_data, 0, 512);
+
+ // Now do the padding if needed
+ for(int i=POIFSConstants.SMALLER_BIG_BLOCK_SIZE; i<bigBlockSize.getBigBlockSize(); i++) {
+ stream.write(0);
+ }
+ }
+}
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockConstants.java Thu Dec 30 02:35:06 2010
@@ -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,31 +14,30 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
import org.apache.poi.poifs.common.POIFSConstants;
-import org.apache.poi.util.IntegerField;
-import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
-import org.apache.poi.util.LongField;
-import org.apache.poi.util.ShortField;
/**
* Constants used in reading/writing the Header block
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
public interface HeaderBlockConstants
{
public static final long _signature = 0xE11AB1A1E011CFD0L;
public static final int _bat_array_offset = 0x4c;
public static final int _max_bats_in_header =
- (POIFSConstants.BIG_BLOCK_SIZE - _bat_array_offset)
- / LittleEndianConsts.INT_SIZE;
+ (POIFSConstants.SMALLER_BIG_BLOCK_SIZE - _bat_array_offset)
+ / LittleEndianConsts.INT_SIZE; // If 4k blocks, rest is blank
+ // Note - in Microsoft terms:
+ // BAT ~= FAT
+ // SBAT ~= MiniFAT
+ // XBAT ~= DIFat
+
// useful offsets
public static final int _signature_offset = 0;
public static final int _bat_count_offset = 0x2C;
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/HeaderBlockWriter.java Thu Dec 30 02:35:06 2010
@@ -19,80 +19,38 @@
package org.apache.poi.poifs.storage;
-import java.io.*;
-
-import java.util.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
-import org.apache.poi.util.IntegerField;
-import org.apache.poi.util.LittleEndianConsts;
-import org.apache.poi.util.LongField;
-import org.apache.poi.util.ShortField;
/**
* The block containing the archive header
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
-public class HeaderBlockWriter
- extends BigBlock
- implements HeaderBlockConstants
+public class HeaderBlockWriter implements HeaderBlockConstants, BlockWritable
{
- private static final byte _default_value = ( byte ) 0xFF;
-
- // number of big block allocation table blocks (int)
- private IntegerField _bat_count;
-
- // start of the property set block (int index of the property set
- // chain's first big block)
- private IntegerField _property_start;
-
- // start of the small block allocation table (int index of small
- // block allocation table's first big block)
- private IntegerField _sbat_start;
-
- // number of big blocks holding the small block allocation table
- private IntegerField _sbat_block_count;
-
- // big block index for extension to the big block allocation table
- private IntegerField _xbat_start;
- private IntegerField _xbat_count;
- private byte[] _data;
+ private final HeaderBlock _header_block;
/**
* Create a single instance initialized with default values
*/
+ public HeaderBlockWriter(POIFSBigBlockSize bigBlockSize)
+ {
+ _header_block = new HeaderBlock(bigBlockSize);
+ }
- public HeaderBlockWriter()
+ /**
+ * Create a single instance initialized with the specified
+ * existing values
+ */
+ public HeaderBlockWriter(HeaderBlock headerBlock)
{
- _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
- Arrays.fill(_data, _default_value);
- new LongField(_signature_offset, _signature, _data);
- new IntegerField(0x08, 0, _data);
- new IntegerField(0x0c, 0, _data);
- new IntegerField(0x10, 0, _data);
- new IntegerField(0x14, 0, _data);
- new ShortField(0x18, ( short ) 0x3b, _data);
- new ShortField(0x1a, ( short ) 0x3, _data);
- new ShortField(0x1c, ( short ) -2, _data);
- new ShortField(0x1e, ( short ) 0x9, _data);
- new IntegerField(0x20, 0x6, _data);
- new IntegerField(0x24, 0, _data);
- new IntegerField(0x28, 0, _data);
- _bat_count = new IntegerField(_bat_count_offset, 0, _data);
- _property_start = new IntegerField(_property_start_offset,
- POIFSConstants.END_OF_CHAIN,
- _data);
- new IntegerField(0x34, 0, _data);
- new IntegerField(0x38, 0x1000, _data);
- _sbat_start = new IntegerField(_sbat_start_offset,
- POIFSConstants.END_OF_CHAIN, _data);
- _sbat_block_count = new IntegerField(_sbat_block_count_offset, 0,
- _data);
- _xbat_start = new IntegerField(_xbat_start_offset,
- POIFSConstants.END_OF_CHAIN, _data);
- _xbat_count = new IntegerField(_xbat_count_offset, 0, _data);
+ _header_block = headerBlock;
}
/**
@@ -111,16 +69,19 @@ public class HeaderBlockWriter
final int startBlock)
{
BATBlock[] rvalue;
+ POIFSBigBlockSize bigBlockSize = _header_block.getBigBlockSize();
- _bat_count.set(blockCount, _data);
- int limit = Math.min(blockCount, _max_bats_in_header);
- int offset = _bat_array_offset;
+ _header_block.setBATCount(blockCount);
- for (int j = 0; j < limit; j++)
- {
- new IntegerField(offset, startBlock + j, _data);
- offset += LittleEndianConsts.INT_SIZE;
+ // Set the BAT locations
+ int limit = Math.min(blockCount, _max_bats_in_header);
+ int[] bat_blocks = new int[limit];
+ for (int j = 0; j < limit; j++) {
+ bat_blocks[j] = startBlock + j;
}
+ _header_block.setBATArray(bat_blocks);
+
+ // Now do the XBATs
if (blockCount > _max_bats_in_header)
{
int excess_blocks = blockCount - _max_bats_in_header;
@@ -131,16 +92,16 @@ public class HeaderBlockWriter
excess_block_array[ j ] = startBlock + j
+ _max_bats_in_header;
}
- rvalue = BATBlock.createXBATBlocks(excess_block_array,
+ rvalue = BATBlock.createXBATBlocks(bigBlockSize, excess_block_array,
startBlock + blockCount);
- _xbat_start.set(startBlock + blockCount, _data);
+ _header_block.setXBATStart(startBlock + blockCount);
}
else
{
- rvalue = BATBlock.createXBATBlocks(new int[ 0 ], 0);
- _xbat_start.set(POIFSConstants.END_OF_CHAIN, _data);
+ rvalue = BATBlock.createXBATBlocks(bigBlockSize, new int[ 0 ], 0);
+ _header_block.setXBATStart(POIFSConstants.END_OF_CHAIN);
}
- _xbat_count.set(rvalue.length, _data);
+ _header_block.setXBATCount(rvalue.length);
return rvalue;
}
@@ -150,10 +111,9 @@ public class HeaderBlockWriter
* @param startBlock the index of the first block of the Property
* Table
*/
-
public void setPropertyStart(final int startBlock)
{
- _property_start.set(startBlock, _data);
+ _header_block.setPropertyStart(startBlock);
}
/**
@@ -162,10 +122,9 @@ public class HeaderBlockWriter
* @param startBlock the index of the first big block of the small
* block allocation table
*/
-
public void setSBATStart(final int startBlock)
{
- _sbat_start.set(startBlock, _data);
+ _header_block.setSBATStart(startBlock);
}
/**
@@ -173,10 +132,9 @@ public class HeaderBlockWriter
*
* @param count the number of SBAT blocks
*/
-
public void setSBATBlockCount(final int count)
{
- _sbat_block_count.set(count, _data);
+ _header_block.setSBATBlockCount(count);
}
/**
@@ -188,11 +146,11 @@ public class HeaderBlockWriter
* @return number of XBAT blocks needed
*/
- static int calculateXBATStorageRequirements(final int blockCount)
+ static int calculateXBATStorageRequirements(POIFSBigBlockSize bigBlockSize, final int blockCount)
{
return (blockCount > _max_bats_in_header)
- ? BATBlock.calculateXBATStorageRequirements(blockCount
- - _max_bats_in_header)
+ ? BATBlock.calculateXBATStorageRequirements(
+ bigBlockSize, blockCount - _max_bats_in_header)
: 0;
}
@@ -207,11 +165,29 @@ public class HeaderBlockWriter
* @exception IOException on problems writing to the specified
* stream
*/
-
- void writeData(final OutputStream stream)
+ public void writeBlocks(final OutputStream stream)
+ throws IOException
+ {
+ _header_block.writeData(stream);
+ }
+
+ /**
+ * Write the block's data to an existing block
+ *
+ * @param block the ByteBuffer of the block to which the
+ * stored data should be written
+ *
+ * @exception IOException on problems writing to the block
+ */
+ public void writeBlock(ByteBuffer block)
throws IOException
{
- doWriteData(stream, _data);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(
+ _header_block.getBigBlockSize().getBigBlockSize()
+ );
+ _header_block.writeData(baos);
+
+ block.put(baos.toByteArray());
}
/* ********** END extension of BigBlock ********** */
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/PropertyBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/PropertyBlock.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/PropertyBlock.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/PropertyBlock.java Thu Dec 30 02:35:06 2010
@@ -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,31 +14,22 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
-import java.io.*;
-
-import java.util.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
-import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.property.Property;
-import org.apache.poi.util.IntegerField;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.LittleEndianConsts;
/**
* A block of Property instances
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
-public class PropertyBlock
- extends BigBlock
-{
- private static final int _properties_per_block =
- POIFSConstants.BIG_BLOCK_SIZE / POIFSConstants.PROPERTY_SIZE;
+public final class PropertyBlock extends BigBlock {
private Property[] _properties;
/**
@@ -49,10 +39,12 @@ public class PropertyBlock
* @param offset the offset into the properties array
*/
- private PropertyBlock(final Property [] properties, final int offset)
+ private PropertyBlock(final POIFSBigBlockSize bigBlockSize, final Property [] properties, final int offset)
{
- _properties = new Property[ _properties_per_block ];
- for (int j = 0; j < _properties_per_block; j++)
+ super(bigBlockSize);
+
+ _properties = new Property[ bigBlockSize.getPropertiesPerBlock() ];
+ for (int j = 0; j < _properties.length; j++)
{
_properties[ j ] = properties[ j + offset ];
}
@@ -70,8 +62,9 @@ public class PropertyBlock
*/
public static BlockWritable [] createPropertyBlockArray(
- final List properties)
+ final POIFSBigBlockSize bigBlockSize, final List<Property> properties)
{
+ int _properties_per_block = bigBlockSize.getPropertiesPerBlock();
int block_count =
(properties.size() + _properties_per_block - 1)
/ _properties_per_block;
@@ -101,7 +94,7 @@ public class PropertyBlock
for (int j = 0; j < block_count; j++)
{
- rvalue[ j ] = new PropertyBlock(to_be_written,
+ rvalue[ j ] = new PropertyBlock(bigBlockSize, to_be_written,
j * _properties_per_block);
}
return rvalue;
@@ -122,6 +115,7 @@ public class PropertyBlock
void writeData(final OutputStream stream)
throws IOException
{
+ int _properties_per_block = bigBlockSize.getPropertiesPerBlock();
for (int j = 0; j < _properties_per_block; j++)
{
_properties[ j ].writeData(stream);
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlock.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlock.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlock.java Thu Dec 30 02:35:06 2010
@@ -51,13 +51,14 @@ public class RawDataBlock
*/
public RawDataBlock(final InputStream stream)
throws IOException {
- this(stream, POIFSConstants.BIG_BLOCK_SIZE);
+ this(stream, POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
}
/**
* Constructor RawDataBlock
*
* @param stream the InputStream from which the data will be read
- * @param blockSize the size of the POIFS blocks, normally 512 bytes {@link POIFSConstants#BIG_BLOCK_SIZE}
+ * @param blockSize the size of the POIFS blocks, normally 512 bytes
+ * {@link org.apache.poi.poifs.common.POIFSConstants#SMALLER_BIG_BLOCK_SIZE}
*
* @exception IOException on I/O errors, and if an insufficient
* amount of data is read (the InputStream must
@@ -111,6 +112,10 @@ public class RawDataBlock
public boolean hasData() {
return _hasData;
}
+
+ public String toString() {
+ return "RawDataBlock of size " + _data.length;
+ }
/* ********** START implementation of ListManagedBlock ********** */
@@ -130,6 +135,13 @@ public class RawDataBlock
}
return _data;
}
+
+ /**
+ * What's the big block size?
+ */
+ public int getBigBlockSize() {
+ return _data.length;
+ }
/* ********** END implementation of ListManagedBlock ********** */
} // end public class RawDataBlock
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java Thu Dec 30 02:35:06 2010
@@ -23,6 +23,8 @@ import java.io.*;
import java.util.*;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
+
/**
* A list of RawDataBlocks instances, and methods to manage the list
*
@@ -43,14 +45,14 @@ public class RawDataBlockList
* block is read
*/
- public RawDataBlockList(final InputStream stream, int bigBlockSize)
+ public RawDataBlockList(final InputStream stream, POIFSBigBlockSize bigBlockSize)
throws IOException
{
- List blocks = new ArrayList();
+ List<RawDataBlock> blocks = new ArrayList<RawDataBlock>();
while (true)
{
- RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
+ RawDataBlock block = new RawDataBlock(stream, bigBlockSize.getBigBlockSize());
// If there was data, add the block to the list
if(block.hasData()) {
@@ -62,7 +64,7 @@ public class RawDataBlockList
break;
}
}
- setBlocks(( RawDataBlock [] ) blocks.toArray(new RawDataBlock[ 0 ]));
+ setBlocks( blocks.toArray(new RawDataBlock[ blocks.size() ]) );
}
} // end public class RawDataBlockList
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java Thu Dec 30 02:35:06 2010
@@ -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,15 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
-import org.apache.poi.poifs.property.RootProperty;
+import java.io.IOException;
-import java.util.*;
-
-import java.io.*;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
+import org.apache.poi.poifs.property.RootProperty;
/**
* This class implements reading the small document block list from an
@@ -31,9 +28,7 @@ import java.io.*;
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
-public class SmallBlockTableReader
-{
+public final class SmallBlockTableReader {
/**
* fetch the small document block list from an existing file
@@ -48,17 +43,23 @@ public class SmallBlockTableReader
*
* @exception IOException
*/
-
public static BlockList getSmallDocumentBlocks(
+ final POIFSBigBlockSize bigBlockSize,
final RawDataBlockList blockList, final RootProperty root,
final int sbatStart)
throws IOException
{
- BlockList list =
- new SmallDocumentBlockList(SmallDocumentBlock
- .extract(blockList.fetchBlocks(root.getStartBlock())));
-
- new BlockAllocationTableReader(blockList.fetchBlocks(sbatStart),
+ // Fetch the blocks which hold the Small Blocks stream
+ ListManagedBlock [] smallBlockBlocks =
+ blockList.fetchBlocks(root.getStartBlock(), -1);
+
+ // Turn that into a list
+ BlockList list =new SmallDocumentBlockList(
+ SmallDocumentBlock.extract(bigBlockSize, smallBlockBlocks));
+
+ // Process
+ new BlockAllocationTableReader(bigBlockSize,
+ blockList.fetchBlocks(sbatStart, -1),
list);
return list;
}
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java Thu Dec 30 02:35:06 2010
@@ -19,6 +19,7 @@
package org.apache.poi.poifs.storage;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.poifs.filesystem.POIFSDocument;
@@ -50,10 +51,11 @@ public class SmallBlockTableWriter
* @param root the Filesystem's root property
*/
- public SmallBlockTableWriter(final List documents,
+ public SmallBlockTableWriter(final POIFSBigBlockSize bigBlockSize,
+ final List documents,
final RootProperty root)
{
- _sbat = new BlockAllocationTableWriter();
+ _sbat = new BlockAllocationTableWriter(bigBlockSize);
_small_blocks = new ArrayList();
_root = root;
Iterator iter = documents.iterator();
@@ -76,7 +78,7 @@ public class SmallBlockTableWriter
}
_sbat.simpleCreateBlocks();
_root.setSize(_small_blocks.size());
- _big_block_count = SmallDocumentBlock.fill(_small_blocks);
+ _big_block_count = SmallDocumentBlock.fill(bigBlockSize,_small_blocks);
}
/**
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java Thu Dec 30 02:35:06 2010
@@ -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,14 +14,17 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
-import java.io.*;
-
-import java.util.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
/**
@@ -31,26 +33,34 @@ import org.apache.poi.poifs.common.POIFS
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
+public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock {
+ private static final int BLOCK_SHIFT = 6;
-public class SmallDocumentBlock
- implements BlockWritable, ListManagedBlock
-{
private byte[] _data;
private static final byte _default_fill = ( byte ) 0xff;
- private static final int _block_size = 64;
- private static final int _blocks_per_big_block =
- POIFSConstants.BIG_BLOCK_SIZE / _block_size;
+ private static final int _block_size = 1 << BLOCK_SHIFT;
+ private static final int BLOCK_MASK = _block_size-1;
- private SmallDocumentBlock(final byte [] data, final int index)
+ private final int _blocks_per_big_block;
+ private final POIFSBigBlockSize _bigBlockSize;
+
+ private SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize, final byte [] data, final int index)
{
- this();
+ this(bigBlockSize);
System.arraycopy(data, index * _block_size, _data, 0, _block_size);
}
- private SmallDocumentBlock()
+ private SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize)
{
+ _bigBlockSize = bigBlockSize;
+ _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
_data = new byte[ _block_size ];
}
+
+ private static int getBlocksPerBigBlock(final POIFSBigBlockSize bigBlockSize)
+ {
+ return bigBlockSize.getBigBlockSize() / _block_size;
+ }
/**
* convert a single long array into an array of SmallDocumentBlock
@@ -62,9 +72,9 @@ public class SmallDocumentBlock
* @return an array of SmallDocumentBlock instances, filled from
* the array
*/
-
- public static SmallDocumentBlock [] convert(final byte [] array,
- final int size)
+ public static SmallDocumentBlock [] convert(POIFSBigBlockSize bigBlockSize,
+ byte [] array,
+ int size)
{
SmallDocumentBlock[] rval =
new SmallDocumentBlock[ (size + _block_size - 1) / _block_size ];
@@ -72,7 +82,7 @@ public class SmallDocumentBlock
for (int k = 0; k < rval.length; k++)
{
- rval[ k ] = new SmallDocumentBlock();
+ rval[ k ] = new SmallDocumentBlock(bigBlockSize);
if (offset < array.length)
{
int length = Math.min(_block_size, array.length - offset);
@@ -101,9 +111,10 @@ public class SmallDocumentBlock
*
* @return number of big blocks the list encompasses
*/
-
- public static int fill(final List blocks)
+ public static int fill(POIFSBigBlockSize bigBlockSize, List blocks)
{
+ int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
+
int count = blocks.size();
int big_block_count = (count + _blocks_per_big_block - 1)
/ _blocks_per_big_block;
@@ -111,7 +122,7 @@ public class SmallDocumentBlock
for (; count < full_count; count++)
{
- blocks.add(makeEmptySmallDocumentBlock());
+ blocks.add(makeEmptySmallDocumentBlock(bigBlockSize));
}
return big_block_count;
}
@@ -128,9 +139,9 @@ public class SmallDocumentBlock
* @exception ArrayIndexOutOfBoundsException if, somehow, the store
* contains less data than size indicates
*/
-
- public static SmallDocumentBlock [] convert(final BlockWritable [] store,
- final int size)
+ public static SmallDocumentBlock [] convert(POIFSBigBlockSize bigBlockSize,
+ BlockWritable [] store,
+ int size)
throws IOException, ArrayIndexOutOfBoundsException
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
@@ -145,7 +156,7 @@ public class SmallDocumentBlock
for (int index = 0; index < rval.length; index++)
{
- rval[ index ] = new SmallDocumentBlock(data, index);
+ rval[ index ] = new SmallDocumentBlock(bigBlockSize, data, index);
}
return rval;
}
@@ -157,13 +168,12 @@ public class SmallDocumentBlock
* data
*
* @return a List of SmallDocumentBlock's extracted from the input
- *
- * @exception IOException
*/
-
- public static List extract(ListManagedBlock [] blocks)
+ public static List extract(POIFSBigBlockSize bigBlockSize, ListManagedBlock [] blocks)
throws IOException
{
+ int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
+
List sdbs = new ArrayList();
for (int j = 0; j < blocks.length; j++)
@@ -172,52 +182,16 @@ public class SmallDocumentBlock
for (int k = 0; k < _blocks_per_big_block; k++)
{
- sdbs.add(new SmallDocumentBlock(data, k));
+ sdbs.add(new SmallDocumentBlock(bigBlockSize, data, k));
}
}
return sdbs;
}
- /**
- * read data from an array of SmallDocumentBlocks
- *
- * @param blocks the blocks to read from
- * @param buffer the buffer to write the data into
- * @param offset the offset into the array of blocks to read from
- */
-
- public static void read(final BlockWritable [] blocks,
- final byte [] buffer, final int offset)
- {
- int firstBlockIndex = offset / _block_size;
- int firstBlockOffset = offset % _block_size;
- int lastBlockIndex = (offset + buffer.length - 1) / _block_size;
-
- if (firstBlockIndex == lastBlockIndex)
- {
- System.arraycopy(
- (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
- firstBlockOffset, buffer, 0, buffer.length);
- }
- else
- {
- int buffer_offset = 0;
-
- System.arraycopy(
- (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
- firstBlockOffset, buffer, buffer_offset,
- _block_size - firstBlockOffset);
- buffer_offset += _block_size - firstBlockOffset;
- for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++)
- {
- System.arraycopy((( SmallDocumentBlock ) blocks[ j ])._data,
- 0, buffer, buffer_offset, _block_size);
- buffer_offset += _block_size;
- }
- System.arraycopy(
- (( SmallDocumentBlock ) blocks[ lastBlockIndex ])._data, 0,
- buffer, buffer_offset, buffer.length - buffer_offset);
- }
+ public static DataInputBlock getDataInputBlock(SmallDocumentBlock[] blocks, int offset) {
+ int firstBlockIndex = offset >> BLOCK_SHIFT;
+ int firstBlockOffset= offset & BLOCK_MASK;
+ return new DataInputBlock(blocks[firstBlockIndex]._data, firstBlockOffset);
}
/**
@@ -227,27 +201,24 @@ public class SmallDocumentBlock
*
* @return total size
*/
-
public static int calcSize(int size)
{
return size * _block_size;
}
- private static SmallDocumentBlock makeEmptySmallDocumentBlock()
+ private static SmallDocumentBlock makeEmptySmallDocumentBlock(POIFSBigBlockSize bigBlockSize)
{
- SmallDocumentBlock block = new SmallDocumentBlock();
+ SmallDocumentBlock block = new SmallDocumentBlock(bigBlockSize);
Arrays.fill(block._data, _default_fill);
return block;
}
- private static int convertToBlockCount(final int size)
+ private static int convertToBlockCount(int size)
{
return (size + _block_size - 1) / _block_size;
}
- /* ********** START implementation of BlockWritable ********** */
-
/**
* Write the storage to an OutputStream
*
@@ -257,16 +228,12 @@ public class SmallDocumentBlock
* @exception IOException on problems writing to the specified
* stream
*/
-
- public void writeBlocks(final OutputStream stream)
+ public void writeBlocks(OutputStream stream)
throws IOException
{
stream.write(_data);
}
- /* ********** END implementation of BlockWritable ********** */
- /* ********** START implementation of ListManagedBlock ********** */
-
/**
* Get the data from the block
*
@@ -274,13 +241,11 @@ public class SmallDocumentBlock
*
* @exception IOException if there is no data
*/
-
- public byte [] getData()
- throws IOException
- {
+ public byte [] getData() {
return _data;
}
-
- /* ********** END implementation of ListManagedBlock ********** */
-} // end public class SmallDocumentBlock
-
+
+ public POIFSBigBlockSize getBigBlockSize() {
+ return _bigBlockSize;
+ }
+}
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java Thu Dec 30 02:35:06 2010
@@ -40,7 +40,7 @@ public class SmallDocumentBlockList
public SmallDocumentBlockList(final List blocks)
{
setBlocks(( SmallDocumentBlock [] ) blocks
- .toArray(new SmallDocumentBlock[ 0 ]));
+ .toArray(new SmallDocumentBlock[ blocks.size() ]));
}
} // end public class SmallDocumentBlockList
Modified: poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/util/ArrayUtil.java
URL: http://svn.apache.org/viewvc/poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/util/ArrayUtil.java?rev=1053791&r1=1053790&r2=1053791&view=diff
==============================================================================
--- poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/util/ArrayUtil.java (original)
+++ poi/branches/NIO_32_BRANCH/src/java/org/apache/poi/util/ArrayUtil.java Thu Dec 30 02:35:06 2010
@@ -21,7 +21,6 @@ package org.apache.poi.util;
* Utility classes for dealing with arrays.
*
* @author Glen Stampoultzis
- * @version $Id$
*/
public class ArrayUtil
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org