| |
| /* ==================================================================== |
| 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.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; |
| |
| /** |
| * The block containing the archive header |
| * |
| * @author Marc Johnson (mjohnson at apache dot org) |
| */ |
| public class HeaderBlockWriter implements HeaderBlockConstants, BlockWritable |
| { |
| private final HeaderBlock _header_block; |
| |
| /** |
| * Create a single instance initialized with default values |
| */ |
| public HeaderBlockWriter(POIFSBigBlockSize bigBlockSize) |
| { |
| _header_block = new HeaderBlock(bigBlockSize); |
| } |
| |
| /** |
| * Create a single instance initialized with the specified |
| * existing values |
| */ |
| public HeaderBlockWriter(HeaderBlock headerBlock) |
| { |
| _header_block = headerBlock; |
| } |
| |
| /** |
| * Set BAT block parameters. Assumes that all BAT blocks are |
| * contiguous. Will construct XBAT blocks if necessary and return |
| * the array of newly constructed XBAT blocks. |
| * |
| * @param blockCount count of BAT blocks |
| * @param startBlock index of first BAT block |
| * |
| * @return array of XBAT blocks; may be zero length, will not be |
| * null |
| */ |
| |
| public BATBlock [] setBATBlocks(final int blockCount, |
| final int startBlock) |
| { |
| BATBlock[] rvalue; |
| POIFSBigBlockSize bigBlockSize = _header_block.getBigBlockSize(); |
| |
| _header_block.setBATCount(blockCount); |
| |
| // 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; |
| int[] excess_block_array = new int[ excess_blocks ]; |
| |
| for (int j = 0; j < excess_blocks; j++) |
| { |
| excess_block_array[ j ] = startBlock + j |
| + _max_bats_in_header; |
| } |
| rvalue = BATBlock.createXBATBlocks(bigBlockSize, excess_block_array, |
| startBlock + blockCount); |
| _header_block.setXBATStart(startBlock + blockCount); |
| } |
| else |
| { |
| rvalue = BATBlock.createXBATBlocks(bigBlockSize, new int[ 0 ], 0); |
| _header_block.setXBATStart(POIFSConstants.END_OF_CHAIN); |
| } |
| _header_block.setXBATCount(rvalue.length); |
| return rvalue; |
| } |
| |
| /** |
| * Set start of Property Table |
| * |
| * @param startBlock the index of the first block of the Property |
| * Table |
| */ |
| public void setPropertyStart(final int startBlock) |
| { |
| _header_block.setPropertyStart(startBlock); |
| } |
| |
| /** |
| * 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) |
| { |
| _header_block.setSBATStart(startBlock); |
| } |
| |
| /** |
| * Set count of SBAT blocks |
| * |
| * @param count the number of SBAT blocks |
| */ |
| public void setSBATBlockCount(final int count) |
| { |
| _header_block.setSBATBlockCount(count); |
| } |
| |
| /** |
| * For a given number of BAT blocks, calculate how many XBAT |
| * blocks will be needed |
| * |
| * @param blockCount number of BAT blocks |
| * |
| * @return number of XBAT blocks needed |
| */ |
| |
| static int calculateXBATStorageRequirements(POIFSBigBlockSize bigBlockSize, final int blockCount) |
| { |
| return (blockCount > _max_bats_in_header) |
| ? BATBlock.calculateXBATStorageRequirements( |
| bigBlockSize, blockCount - _max_bats_in_header) |
| : 0; |
| } |
| |
| /* ********** START extension of BigBlock ********** */ |
| |
| /** |
| * 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 |
| */ |
| 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 |
| { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream( |
| _header_block.getBigBlockSize().getBigBlockSize() |
| ); |
| _header_block.writeData(baos); |
| |
| block.put(baos.toByteArray()); |
| } |
| |
| /* ********** END extension of BigBlock ********** */ |
| } // end public class HeaderBlockWriter |
| |