package org.apache.poi.poifs.storage;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._bat_array_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._bat_count_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._max_bats_in_header;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._property_start_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._sbat_start_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._sbat_block_count_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._signature;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._signature_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._xbat_count_offset;
-import static org.apache.poi.poifs.storage.HeaderBlockConstants._xbat_start_offset;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.IntegerField;
/**
* The block containing the archive header
*/
-public final class HeaderBlock {
+public final class HeaderBlock implements HeaderBlockConstants {
private static final POILogger _logger =
POILogFactory.getLogger(HeaderBlock.class);
/**
* Create a single instance initialized with default values
*/
- public HeaderBlock(POIFSBigBlockSize bigBlockSize) throws IOException
+ public HeaderBlock(POIFSBigBlockSize bigBlockSize)
{
this.bigBlockSize = bigBlockSize;
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 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
*/
public int[] getBATArray() {
// Read them in
- int[] result = new int[ _bat_count ];
+ int[] result = new int[ Math.min(_bat_count,_max_bats_in_header) ];
int offset = _bat_array_offset;
for (int j = 0; j < _bat_count; j++) {
result[ j ] = LittleEndian.getInt(_data, offset);
}
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
stream.write(_data, 0, 512);
// Now do the padding if needed
- for(int i=POIFSConstants.SMALLER_BIG_BLOCK_SIZE; i<POIFSConstants.LARGER_BIG_BLOCK_SIZE; i++) {
+ for(int i=POIFSConstants.SMALLER_BIG_BLOCK_SIZE; i<bigBlockSize.getBigBlockSize(); i++) {
stream.write(0);
}
}
package org.apache.poi.poifs.storage;
-import java.io.*;
-
-import java.util.*;
+import java.io.IOException;
+import java.io.OutputStream;
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)
{
- super(bigBlockSize);
-
- _data = new byte[ bigBlockSize.getBigBlockSize() ];
- 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, bigBlockSize.getHeaderValue(), _data);
- if(bigBlockSize.getBigBlockSize() == POIFSConstants.LARGER_BIG_BLOCK_SIZE) {
- // Need to fill the extra header size with zeros
- for(int i=POIFSConstants.SMALLER_BIG_BLOCK_SIZE; i<_data.length; i++) {
- _data[i] = 0;
- }
- }
-
- 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 = new HeaderBlock(bigBlockSize);
}
/**
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;
}
rvalue = BATBlock.createXBATBlocks(bigBlockSize, excess_block_array,
startBlock + blockCount);
- _xbat_start.set(startBlock + blockCount, _data);
+ _header_block.setXBATStart(startBlock + blockCount);
}
else
{
rvalue = BATBlock.createXBATBlocks(bigBlockSize, new int[ 0 ], 0);
- _xbat_start.set(POIFSConstants.END_OF_CHAIN, _data);
+ _header_block.setXBATStart(POIFSConstants.END_OF_CHAIN);
}
- _xbat_count.set(rvalue.length, _data);
+ _header_block.setXBATCount(rvalue.length);
return rvalue;
}
* @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);
}
/**
* @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);
}
/**
*
* @param count the number of SBAT blocks
*/
-
public void setSBATBlockCount(final int count)
{
- _sbat_block_count.set(count, _data);
+ _header_block.setSBATBlockCount(count);
}
/**
* stream
*/
- void writeData(final OutputStream stream)
+ public void writeBlocks(final OutputStream stream)
throws IOException
{
- doWriteData(stream, _data);
+ _header_block.writeData(stream);
}
/* ********** END extension of BigBlock ********** */