You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BlockAllocationTableWriter.java 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.storage;
  16. import java.io.IOException;
  17. import java.io.OutputStream;
  18. import java.nio.ByteBuffer;
  19. import org.apache.poi.poifs.common.POIFSBigBlockSize;
  20. import org.apache.poi.poifs.common.POIFSConstants;
  21. import org.apache.poi.poifs.filesystem.BATManaged;
  22. import org.apache.poi.util.IntList;
  23. /**
  24. * This class manages and creates the Block Allocation Table, which is
  25. * basically a set of linked lists of block indices.
  26. * <P>
  27. * Each block of the filesystem has an index. The first block, the
  28. * header, is skipped; the first block after the header is index 0,
  29. * the next is index 1, and so on.
  30. * <P>
  31. * A block's index is also its index into the Block Allocation
  32. * Table. The entry that it finds in the Block Allocation Table is the
  33. * index of the next block in the linked list of blocks making up a
  34. * file, or it is set to -2: end of list.
  35. *
  36. * @author Marc Johnson (mjohnson at apache dot org)
  37. */
  38. public final class BlockAllocationTableWriter implements BlockWritable, BATManaged {
  39. private IntList _entries;
  40. private BATBlock[] _blocks;
  41. private int _start_block;
  42. private POIFSBigBlockSize _bigBlockSize;
  43. /**
  44. * create a BlockAllocationTableWriter
  45. */
  46. public BlockAllocationTableWriter(POIFSBigBlockSize bigBlockSize)
  47. {
  48. _bigBlockSize = bigBlockSize;
  49. _start_block = POIFSConstants.END_OF_CHAIN;
  50. _entries = new IntList();
  51. _blocks = new BATBlock[ 0 ];
  52. }
  53. /**
  54. * Create the BATBlocks we need
  55. *
  56. * @return start block index of BAT blocks
  57. */
  58. public int createBlocks()
  59. {
  60. int xbat_blocks = 0;
  61. int bat_blocks = 0;
  62. while (true)
  63. {
  64. int calculated_bat_blocks =
  65. BATBlock.calculateStorageRequirements(_bigBlockSize,
  66. bat_blocks
  67. + xbat_blocks
  68. + _entries.size());
  69. int calculated_xbat_blocks =
  70. HeaderBlockWriter.calculateXBATStorageRequirements(
  71. _bigBlockSize, calculated_bat_blocks);
  72. if ((bat_blocks == calculated_bat_blocks)
  73. && (xbat_blocks == calculated_xbat_blocks))
  74. {
  75. // stable ... we're OK
  76. break;
  77. }
  78. bat_blocks = calculated_bat_blocks;
  79. xbat_blocks = calculated_xbat_blocks;
  80. }
  81. int startBlock = allocateSpace(bat_blocks);
  82. allocateSpace(xbat_blocks);
  83. simpleCreateBlocks();
  84. return startBlock;
  85. }
  86. /**
  87. * Allocate space for a block of indices
  88. *
  89. * @param blockCount the number of blocks to allocate space for
  90. *
  91. * @return the starting index of the blocks
  92. */
  93. public int allocateSpace(final int blockCount)
  94. {
  95. int startBlock = _entries.size();
  96. if (blockCount > 0)
  97. {
  98. int limit = blockCount - 1;
  99. int index = startBlock + 1;
  100. for (int k = 0; k < limit; k++)
  101. {
  102. _entries.add(index++);
  103. }
  104. _entries.add(POIFSConstants.END_OF_CHAIN);
  105. }
  106. return startBlock;
  107. }
  108. /**
  109. * get the starting block
  110. *
  111. * @return the starting block index
  112. */
  113. public int getStartBlock()
  114. {
  115. return _start_block;
  116. }
  117. /**
  118. * create the BATBlocks
  119. */
  120. void simpleCreateBlocks()
  121. {
  122. _blocks = BATBlock.createBATBlocks(_bigBlockSize, _entries.toArray());
  123. }
  124. /**
  125. * Write the storage to an OutputStream
  126. *
  127. * @param stream the OutputStream to which the stored data should
  128. * be written
  129. *
  130. * @exception IOException on problems writing to the specified
  131. * stream
  132. */
  133. public void writeBlocks(final OutputStream stream)
  134. throws IOException
  135. {
  136. for (int j = 0; j < _blocks.length; j++)
  137. {
  138. _blocks[ j ].writeBlocks(stream);
  139. }
  140. }
  141. /**
  142. * Write the BAT into its associated block
  143. */
  144. public static void writeBlock(final BATBlock bat, final ByteBuffer block)
  145. throws IOException
  146. {
  147. bat.writeData(block);
  148. }
  149. /**
  150. * Return the number of BigBlock's this instance uses
  151. *
  152. * @return count of BigBlock instances
  153. */
  154. public int countBlocks()
  155. {
  156. return _blocks.length;
  157. }
  158. /**
  159. * Set the start block for this instance
  160. */
  161. public void setStartBlock(int start_block)
  162. {
  163. _start_block = start_block;
  164. }
  165. }