1 2 17 18 19 package org.apache.poi.poifs.storage; 20 21 import java.io.IOException ; 22 import java.io.OutputStream ; 23 24 import java.util.*; 25 26 import org.apache.poi.poifs.common.POIFSConstants; 27 import org.apache.poi.util.IntList; 28 import org.apache.poi.util.LittleEndian; 29 import org.apache.poi.util.LittleEndianConsts; 30 31 46 47 public class BlockAllocationTableReader 48 { 49 private IntList _entries; 50 51 69 70 public BlockAllocationTableReader(final int block_count, 71 final int [] block_array, 72 final int xbat_count, 73 final int xbat_index, 74 final BlockList raw_block_list) 75 throws IOException 76 { 77 this(); 78 if (block_count <= 0) 79 { 80 throw new IOException ( 81 "Illegal block count; minimum count is 1, got " + block_count 82 + " instead"); 83 } 84 85 RawDataBlock blocks[] = new RawDataBlock[ block_count ]; 87 int limit = Math.min(block_count, block_array.length); 88 int block_index; 89 90 for (block_index = 0; block_index < limit; block_index++) 91 { 92 blocks[ block_index ] = 93 ( RawDataBlock ) raw_block_list 94 .remove(block_array[ block_index ]); 95 } 96 if (block_index < block_count) 97 { 98 99 if (xbat_index < 0) 101 { 102 throw new IOException ( 103 "BAT count exceeds limit, yet XBAT index indicates no valid entries"); 104 } 105 int chain_index = xbat_index; 106 int max_entries_per_block = BATBlock.entriesPerXBATBlock(); 107 int chain_index_offset = BATBlock.getXBATChainOffset(); 108 109 for (int j = 0; j < xbat_count; j++) 110 { 111 limit = Math.min(block_count - block_index, 112 max_entries_per_block); 113 byte[] data = raw_block_list.remove(chain_index).getData(); 114 int offset = 0; 115 116 for (int k = 0; k < limit; k++) 117 { 118 blocks[ block_index++ ] = 119 ( RawDataBlock ) raw_block_list 120 .remove(LittleEndian.getInt(data, offset)); 121 offset += LittleEndianConsts.INT_SIZE; 122 } 123 chain_index = LittleEndian.getInt(data, chain_index_offset); 124 if (chain_index == POIFSConstants.END_OF_CHAIN) 125 { 126 break; 127 } 128 } 129 } 130 if (block_index != block_count) 131 { 132 throw new IOException ("Could not find all blocks"); 133 } 134 135 setEntries(blocks, raw_block_list); 138 } 139 140 148 149 BlockAllocationTableReader(final ListManagedBlock [] blocks, 150 final BlockList raw_block_list) 151 throws IOException 152 { 153 this(); 154 setEntries(blocks, raw_block_list); 155 } 156 157 162 163 BlockAllocationTableReader() 164 { 165 _entries = new IntList(); 166 } 167 168 180 181 ListManagedBlock [] fetchBlocks(final int startBlock, 182 final BlockList blockList) 183 throws IOException 184 { 185 List blocks = new ArrayList(); 186 int currentBlock = startBlock; 187 188 while (currentBlock != POIFSConstants.END_OF_CHAIN) 189 { 190 blocks.add(blockList.remove(currentBlock)); 191 currentBlock = _entries.get(currentBlock); 192 } 193 return ( ListManagedBlock [] ) blocks 194 .toArray(new ListManagedBlock[ 0 ]); 195 } 196 197 199 206 207 boolean isUsed(final int index) 208 { 209 boolean rval = false; 210 211 try 212 { 213 rval = _entries.get(index) != -1; 214 } 215 catch (IndexOutOfBoundsException ignored) 216 { 217 } 218 return rval; 219 } 220 221 232 233 int getNextBlockIndex(final int index) 234 throws IOException 235 { 236 if (isUsed(index)) 237 { 238 return _entries.get(index); 239 } 240 else 241 { 242 throw new IOException ("index " + index + " is unused"); 243 } 244 } 245 246 255 256 private void setEntries(final ListManagedBlock [] blocks, 257 final BlockList raw_blocks) 258 throws IOException 259 { 260 int limit = BATBlock.entriesPerBlock(); 261 262 for (int block_index = 0; block_index < blocks.length; block_index++) 263 { 264 byte[] data = blocks[ block_index ].getData(); 265 int offset = 0; 266 267 for (int k = 0; k < limit; k++) 268 { 269 int entry = LittleEndian.getInt(data, offset); 270 271 if (entry == POIFSConstants.UNUSED_BLOCK) 272 { 273 raw_blocks.zap(_entries.size()); 274 } 275 _entries.add(entry); 276 offset += LittleEndianConsts.INT_SIZE; 277 } 278 279 blocks[ block_index ] = null; 281 } 282 raw_blocks.setBAT(this); 283 } 284 } 286 | Popular Tags |