1 19 20 package jxl.read.biff; 21 22 import java.util.ArrayList ; 23 import java.util.Iterator ; 24 25 import common.Logger; 26 27 import jxl.WorkbookSettings; 28 import jxl.biff.BaseCompoundFile; 29 import jxl.biff.IntegerHelper; 30 31 35 public final class CompoundFile extends BaseCompoundFile 36 { 37 40 private static Logger logger = Logger.getLogger(CompoundFile.class); 41 42 46 private byte[] data; 47 50 private int numBigBlockDepotBlocks; 51 54 private int sbdStartBlock; 55 58 private int rootStartBlock; 59 62 private int extensionBlock; 63 66 private int numExtensionBlocks; 67 70 private byte[] rootEntry; 71 74 private int[] bigBlockChain; 75 78 private int[] smallBlockChain; 79 82 private int[] bigBlockDepotBlocks; 83 86 private ArrayList propertySets; 87 88 91 private WorkbookSettings settings; 92 93 100 public CompoundFile(byte[] d, WorkbookSettings ws) throws BiffException 101 { 102 super(); 103 data = d; 104 settings = ws; 105 106 for (int i = 0; i < IDENTIFIER.length; i++) 108 { 109 if (data[i] != IDENTIFIER[i]) 110 { 111 throw new BiffException(BiffException.unrecognizedOLEFile); 112 } 113 } 114 115 propertySets = new ArrayList (); 116 numBigBlockDepotBlocks = IntegerHelper.getInt 117 (data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS], 118 data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 1], 119 data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 2], 120 data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 3]); 121 sbdStartBlock = IntegerHelper.getInt 122 (data[SMALL_BLOCK_DEPOT_BLOCK_POS], 123 data[SMALL_BLOCK_DEPOT_BLOCK_POS + 1], 124 data[SMALL_BLOCK_DEPOT_BLOCK_POS + 2], 125 data[SMALL_BLOCK_DEPOT_BLOCK_POS + 3]); 126 rootStartBlock = IntegerHelper.getInt 127 (data[ROOT_START_BLOCK_POS], 128 data[ROOT_START_BLOCK_POS + 1], 129 data[ROOT_START_BLOCK_POS + 2], 130 data[ROOT_START_BLOCK_POS + 3]); 131 extensionBlock = IntegerHelper.getInt 132 (data[EXTENSION_BLOCK_POS], 133 data[EXTENSION_BLOCK_POS + 1], 134 data[EXTENSION_BLOCK_POS + 2], 135 data[EXTENSION_BLOCK_POS + 3]); 136 numExtensionBlocks = IntegerHelper.getInt 137 (data[NUM_EXTENSION_BLOCK_POS], 138 data[NUM_EXTENSION_BLOCK_POS + 1], 139 data[NUM_EXTENSION_BLOCK_POS + 2], 140 data[NUM_EXTENSION_BLOCK_POS + 3]); 141 142 bigBlockDepotBlocks = new int[numBigBlockDepotBlocks]; 143 144 int pos = BIG_BLOCK_DEPOT_BLOCKS_POS; 145 146 int bbdBlocks = numBigBlockDepotBlocks; 147 148 if (numExtensionBlocks != 0) 149 { 150 bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; 151 } 152 153 for (int i = 0; i < bbdBlocks; i++) 154 { 155 bigBlockDepotBlocks[i] = IntegerHelper.getInt 156 (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); 157 pos += 4; 158 } 159 160 for (int j = 0; j < numExtensionBlocks; j++) 161 { 162 pos = (extensionBlock + 1) * BIG_BLOCK_SIZE; 163 int blocksToRead = Math.min(numBigBlockDepotBlocks - bbdBlocks, 164 BIG_BLOCK_SIZE / 4 - 1); 165 166 for (int i = bbdBlocks; i < bbdBlocks + blocksToRead; i++) 167 { 168 bigBlockDepotBlocks[i] = IntegerHelper.getInt 169 (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); 170 pos += 4; 171 } 172 173 bbdBlocks += blocksToRead; 174 if (bbdBlocks < numBigBlockDepotBlocks) 175 { 176 extensionBlock = IntegerHelper.getInt 177 (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); 178 } 179 } 180 181 readBigBlockDepot(); 182 readSmallBlockDepot(); 183 184 rootEntry = readData(rootStartBlock); 185 readPropertySets(); 186 } 187 188 191 private void readBigBlockDepot() 192 { 193 int pos = 0; 194 int index = 0; 195 bigBlockChain = new int[numBigBlockDepotBlocks * BIG_BLOCK_SIZE / 4]; 196 197 for (int i = 0; i < numBigBlockDepotBlocks; i++) 198 { 199 pos = (bigBlockDepotBlocks[i] + 1) * BIG_BLOCK_SIZE; 200 201 for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++) 202 { 203 bigBlockChain[index] = IntegerHelper.getInt 204 (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); 205 pos += 4; 206 index++; 207 } 208 } 209 } 210 211 214 private void readSmallBlockDepot() 215 { 216 int pos = 0; 217 int index = 0; 218 int sbdBlock = sbdStartBlock; 219 smallBlockChain = new int[0]; 220 221 while (sbdBlock != -2) 222 { 223 int[] oldChain = smallBlockChain; 225 smallBlockChain = new int[smallBlockChain.length + BIG_BLOCK_SIZE / 4]; 226 System.arraycopy(oldChain, 0, smallBlockChain, 0, oldChain.length); 227 228 pos = (sbdBlock + 1) * BIG_BLOCK_SIZE; 229 230 for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++) 231 { 232 smallBlockChain[index] = IntegerHelper.getInt 233 (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); 234 pos += 4; 235 index++; 236 } 237 238 sbdBlock = bigBlockChain[sbdBlock]; 239 } 240 } 241 242 245 private void readPropertySets() 246 { 247 int offset = 0; 248 byte[] d = null; 249 250 while (offset < rootEntry.length) 251 { 252 d = new byte[PROPERTY_STORAGE_BLOCK_SIZE]; 253 System.arraycopy(rootEntry, offset, d, 0, d.length); 254 PropertyStorage ps = new PropertyStorage(d); 255 256 if (ps.name == null || ps.name.length() == 0) 259 { 260 if (ps.type == ROOT_ENTRY_PS_TYPE) 261 { 262 ps.name = ROOT_ENTRY_NAME; 263 logger.warn("Property storage name for " + ps.type + 264 " is empty - setting to " + ROOT_ENTRY_NAME); 265 } 266 else 267 { 268 logger.warn("Property storage type " + ps.type + 269 " has no associated name"); 270 } 271 272 } 273 propertySets.add(ps); 274 offset += PROPERTY_STORAGE_BLOCK_SIZE; 275 } 276 } 277 278 285 public byte[] getStream(String streamName) throws BiffException 286 { 287 PropertyStorage ps = getPropertyStorage(streamName); 288 289 if (ps.size >= SMALL_BLOCK_THRESHOLD || 290 streamName.equalsIgnoreCase(ROOT_ENTRY_NAME)) 291 { 292 return getBigBlockStream(ps); 293 } 294 else 295 { 296 return getSmallBlockStream(ps); 297 } 298 } 299 300 306 private PropertyStorage getPropertyStorage(String name) 307 throws BiffException 308 { 309 Iterator i = propertySets.iterator(); 311 boolean found = false; 312 PropertyStorage ps = null; 313 while (!found && i.hasNext()) 314 { 315 ps = (PropertyStorage) i.next(); 316 if (ps.name.equalsIgnoreCase(name)) 317 { 318 found = true; 319 } 320 } 321 322 if (!found) 323 { 324 throw new BiffException(BiffException.streamNotFound); 325 } 326 327 return ps; 328 } 329 330 336 private byte[] getBigBlockStream(PropertyStorage ps) 337 { 338 int numBlocks = ps.size / BIG_BLOCK_SIZE; 339 if (ps.size % BIG_BLOCK_SIZE != 0) 340 { 341 numBlocks++; 342 } 343 344 byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE]; 345 346 int block = ps.startBlock; 347 348 int count = 0; 349 int pos = 0; 350 while (block != -2 && count < numBlocks) 351 { 352 pos = (block + 1) * BIG_BLOCK_SIZE; 353 System.arraycopy(data, pos, streamData, 354 count * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE); 355 count++; 356 block = bigBlockChain[block]; 357 } 358 359 if (block != -2 && count == numBlocks) 360 { 361 logger.warn("Property storage size inconsistent with block chain."); 362 } 363 364 return streamData; 365 } 366 367 373 private byte[] getSmallBlockStream(PropertyStorage ps) 374 throws BiffException 375 { 376 PropertyStorage rootps = null; 377 try 378 { 379 rootps = getPropertyStorage(ROOT_ENTRY_NAME); 380 } 381 catch (BiffException e) 382 { 383 rootps = (PropertyStorage) propertySets.get(0); 384 } 385 386 byte[] rootdata = readData(rootps.startBlock); 387 byte[] sbdata = new byte[0]; 388 389 int block = ps.startBlock; 390 int pos = 0; 391 while (block != -2) 392 { 393 byte[] olddata = sbdata; 395 sbdata = new byte[olddata.length + SMALL_BLOCK_SIZE]; 396 System.arraycopy(olddata, 0, sbdata, 0, olddata.length); 397 398 pos = block * SMALL_BLOCK_SIZE; 400 System.arraycopy(rootdata, pos, sbdata, 401 olddata.length, SMALL_BLOCK_SIZE); 402 block = smallBlockChain[block]; 403 } 404 405 return sbdata; 406 } 407 408 415 private byte[] readData(int bl) 416 { 417 int block = bl; 418 int pos = 0; 419 byte[] entry = new byte[0]; 420 421 while (block != -2) 422 { 423 byte[] oldEntry = entry; 425 entry = new byte[oldEntry.length + BIG_BLOCK_SIZE]; 426 System.arraycopy(oldEntry, 0, entry, 0, oldEntry.length); 427 pos = (block + 1) * BIG_BLOCK_SIZE; 428 System.arraycopy(data, pos, entry, 429 oldEntry.length, BIG_BLOCK_SIZE); 430 block = bigBlockChain[block]; 431 } 432 return entry; 433 } 434 435 439 public String [] getPropertySetNames() 440 { 441 String [] sets = new String [propertySets.size()]; 442 for (int i = 0; i < sets.length; i++) 443 { 444 PropertyStorage ps = (PropertyStorage) propertySets.get(i); 445 sets[i] = ps.name; 446 } 447 448 return sets; 449 } 450 451 457 public PropertyStorage getPropertySet(String ps) 458 { 459 boolean found = false; 460 PropertyStorage propertySet = null; 461 for (Iterator i = propertySets.iterator() ; i.hasNext() && !found ; ) 462 { 463 propertySet = (PropertyStorage) i.next(); 464 if (propertySet.name.equalsIgnoreCase(ps)) 465 { 466 found = true; 467 } 468 } 469 470 return found ? propertySet : null; 471 } 472 } 473 474 475 476 477 478 479 480 481 482 483 484 485 | Popular Tags |