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