1 2 /* ==================================================================== 3 * The Apache Software License, Version 1.1 4 * 5 * Copyright (c) 2002 The Apache Software Foundation. All rights 6 * reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The end-user documentation included with the redistribution, 21 * if any, must include the following acknowledgment: 22 * "This product includes software developed by the 23 * Apache Software Foundation (http://www.apache.org/)." 24 * Alternately, this acknowledgment may appear in the software itself, 25 * if and wherever such third-party acknowledgments normally appear. 26 * 27 * 4. The names "Apache" and "Apache Software Foundation" and 28 * "Apache POI" must not be used to endorse or promote products 29 * derived from this software without prior written permission. For 30 * written permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * "Apache POI", nor may "Apache" appear in their name, without 34 * prior written permission of the Apache Software Foundation. 35 * 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This software consists of voluntary contributions made by many 51 * individuals on behalf of the Apache Software Foundation. For more 52 * information on the Apache Software Foundation, please see 53 * <http://www.apache.org/>. 54 */ 55 56 package org.apache.poi.poifs.storage; 57 58 import java.io.IOException; 59 import java.io.OutputStream; 60 61 import java.util.*; 62 63 import org.apache.poi.poifs.common.POIFSConstants; 64 import org.apache.poi.poifs.filesystem.BATManaged; 65 import org.apache.poi.util.IntList; 66 import org.apache.poi.util.LittleEndian; 67 import org.apache.poi.util.LittleEndianConsts; 68 69 /** 70 * This class manages and creates the Block Allocation Table, which is 71 * basically a set of linked lists of block indices. 72 * <P> 73 * Each block of the filesystem has an index. The first block, the 74 * header, is skipped; the first block after the header is index 0, 75 * the next is index 1, and so on. 76 * <P> 77 * A block's index is also its index into the Block Allocation 78 * Table. The entry that it finds in the Block Allocation Table is the 79 * index of the next block in the linked list of blocks making up a 80 * file, or it is set to -2: end of list. 81 * 82 * @author Marc Johnson (mjohnson at apache dot org) 83 */ 84 85 public class BlockAllocationTableWriter 86 implements BlockWritable, BATManaged 87 { 88 private IntList _entries; 89 private BATBlock[] _blocks; 90 private int _start_block; 91 92 /** 93 * create a BlockAllocationTableWriter 94 */ 95 96 public BlockAllocationTableWriter() 97 { 98 _start_block = POIFSConstants.END_OF_CHAIN; 99 _entries = new IntList(); 100 _blocks = new BATBlock[ 0 ]; 101 } 102 103 /** 104 * Create the BATBlocks we need 105 * 106 * @return start block index of BAT blocks 107 */ 108 109 public int createBlocks() 110 { 111 int xbat_blocks = 0; 112 int bat_blocks = 0; 113 114 while (true) 115 { 116 int calculated_bat_blocks = 117 BATBlock.calculateStorageRequirements(bat_blocks 118 + xbat_blocks 119 + _entries.size()); 120 int calculated_xbat_blocks = 121 HeaderBlockWriter 122 .calculateXBATStorageRequirements(calculated_bat_blocks); 123 124 if ((bat_blocks == calculated_bat_blocks) 125 && (xbat_blocks == calculated_xbat_blocks)) 126 { 127 128 // stable ... we're OK 129 break; 130 } 131 else 132 { 133 bat_blocks = calculated_bat_blocks; 134 xbat_blocks = calculated_xbat_blocks; 135 } 136 } 137 int startBlock = allocateSpace(bat_blocks); 138 139 allocateSpace(xbat_blocks); 140 simpleCreateBlocks(); 141 return startBlock; 142 } 143 144 /** 145 * Allocate space for a block of indices 146 * 147 * @param blockCount the number of blocks to allocate space for 148 * 149 * @return the starting index of the blocks 150 */ 151 152 public int allocateSpace(final int blockCount) 153 { 154 int startBlock = _entries.size(); 155 156 if (blockCount > 0) 157 { 158 int limit = blockCount - 1; 159 int index = startBlock + 1; 160 161 for (int k = 0; k < limit; k++) 162 { 163 _entries.add(index++); 164 } 165 _entries.add(POIFSConstants.END_OF_CHAIN); 166 } 167 return startBlock; 168 } 169 170 /** 171 * get the starting block 172 * 173 * @return the starting block index 174 */ 175 176 public int getStartBlock() 177 { 178 return _start_block; 179 } 180 181 /** 182 * create the BATBlocks 183 */ 184 185 void simpleCreateBlocks() 186 { 187 _blocks = BATBlock.createBATBlocks(_entries.toArray()); 188 } 189 190 /* ********** START implementation of BlockWritable ********** */ 191 192 /** 193 * Write the storage to an OutputStream 194 * 195 * @param stream the OutputStream to which the stored data should 196 * be written 197 * 198 * @exception IOException on problems writing to the specified 199 * stream 200 */ 201 202 public void writeBlocks(final OutputStream stream) 203 throws IOException 204 { 205 for (int j = 0; j < _blocks.length; j++) 206 { 207 _blocks[ j ].writeBlocks(stream); 208 } 209 } 210 211 /* ********** END implementation of BlockWritable ********** */ 212 /* ********** START implementation of BATManaged ********** */ 213 214 /** 215 * Return the number of BigBlock's this instance uses 216 * 217 * @return count of BigBlock instances 218 */ 219 220 public int countBlocks() 221 { 222 return _blocks.length; 223 } 224 225 /** 226 * Set the start block for this instance 227 * 228 * @param index index into the array of BigBlock instances making 229 * up the the filesystem 230 * 231 * @param start_block 232 */ 233 234 public void setStartBlock(int start_block) 235 { 236 _start_block = start_block; 237 } 238 239 /* ********** END implementation of BATManaged ********** */ 240 } // end class BlockAllocationTableWriter 241 242