123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /* ====================================================================
- 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.OutputStream;
- import java.nio.ByteBuffer;
-
- 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.util.IntList;
-
- /**
- * This class manages and creates the Block Allocation Table, which is
- * basically a set of linked lists of block indices.
- * <P>
- * Each block of the filesystem has an index. The first block, the
- * header, is skipped; the first block after the header is index 0,
- * the next is index 1, and so on.
- * <P>
- * A block's index is also its index into the Block Allocation
- * Table. The entry that it finds in the Block Allocation Table is the
- * index of the next block in the linked list of blocks making up a
- * file, or it is set to -2: end of list.
- *
- * @author Marc Johnson (mjohnson at apache dot org)
- */
- public final class BlockAllocationTableWriter implements BlockWritable, BATManaged {
- private IntList _entries;
- private BATBlock[] _blocks;
- private int _start_block;
- private POIFSBigBlockSize _bigBlockSize;
-
- /**
- * create a BlockAllocationTableWriter
- */
- public BlockAllocationTableWriter(POIFSBigBlockSize bigBlockSize)
- {
- _bigBlockSize = bigBlockSize;
- _start_block = POIFSConstants.END_OF_CHAIN;
- _entries = new IntList();
- _blocks = new BATBlock[ 0 ];
- }
-
- /**
- * Create the BATBlocks we need
- *
- * @return start block index of BAT blocks
- */
- public int createBlocks()
- {
- int xbat_blocks = 0;
- int bat_blocks = 0;
-
- while (true)
- {
- int calculated_bat_blocks =
- BATBlock.calculateStorageRequirements(_bigBlockSize,
- bat_blocks
- + xbat_blocks
- + _entries.size());
- int calculated_xbat_blocks =
- HeaderBlockWriter.calculateXBATStorageRequirements(
- _bigBlockSize, calculated_bat_blocks);
-
- if ((bat_blocks == calculated_bat_blocks)
- && (xbat_blocks == calculated_xbat_blocks))
- {
-
- // stable ... we're OK
- break;
- }
- bat_blocks = calculated_bat_blocks;
- xbat_blocks = calculated_xbat_blocks;
- }
- int startBlock = allocateSpace(bat_blocks);
-
- allocateSpace(xbat_blocks);
- simpleCreateBlocks();
- return startBlock;
- }
-
- /**
- * Allocate space for a block of indices
- *
- * @param blockCount the number of blocks to allocate space for
- *
- * @return the starting index of the blocks
- */
- public int allocateSpace(final int blockCount)
- {
- int startBlock = _entries.size();
-
- if (blockCount > 0)
- {
- int limit = blockCount - 1;
- int index = startBlock + 1;
-
- for (int k = 0; k < limit; k++)
- {
- _entries.add(index++);
- }
- _entries.add(POIFSConstants.END_OF_CHAIN);
- }
- return startBlock;
- }
-
- /**
- * get the starting block
- *
- * @return the starting block index
- */
- public int getStartBlock()
- {
- return _start_block;
- }
-
- /**
- * create the BATBlocks
- */
- void simpleCreateBlocks()
- {
- _blocks = BATBlock.createBATBlocks(_bigBlockSize, _entries.toArray());
- }
-
- /**
- * Write the storage to an OutputStream
- *
- * @param stream the OutputStream to which the stored data should
- * be written
- *
- * @exception IOException on problems writing to the specified
- * stream
- */
- public void writeBlocks(final OutputStream stream)
- throws IOException
- {
- for (int j = 0; j < _blocks.length; j++)
- {
- _blocks[ j ].writeBlocks(stream);
- }
- }
-
- /**
- * Write the BAT into its associated block
- */
- public static void writeBlock(final BATBlock bat, final ByteBuffer block)
- throws IOException
- {
- bat.writeData(block);
- }
-
- /**
- * Return the number of BigBlock's this instance uses
- *
- * @return count of BigBlock instances
- */
- public int countBlocks()
- {
- return _blocks.length;
- }
-
- /**
- * Set the start block for this instance
- */
- public void setStartBlock(int start_block)
- {
- _start_block = start_block;
- }
- }
|