CompoundFile.java 源代码
package jxl.write.biff;
import common.Assert;
import common.Logger;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import jxl.biff.BaseCompoundFile;
import jxl.biff.IntegerHelper;
import jxl.read.biff.BiffException;
import org.apache.poi.ss.formula.ptg.UnionPtg;
final class CompoundFile extends BaseCompoundFile {
static Class class$jxl$write$biff$CompoundFile;
private static Logger logger;
private int additionalPropertyBlocks;
private ArrayList additionalPropertySets;
private int bbdPos;
private int bbdStartBlock;
private byte[] bigBlockDepot;
private byte[] excelData;
private int excelDataBlocks;
private int excelDataStartBlock;
private int extensionBlock;
private int numBigBlockDepotBlocks;
private int numExtensionBlocks;
private int numPropertySets;
private int numRootEntryBlocks;
private int numSmallBlockDepotBlocks;
private int numSmallBlockDepotChainBlocks;
private int numSmallBlocks;
private OutputStream out;
private int requiredSize;
private int rootStartBlock;
private int sbdStartBlock;
private int sbdStartBlockChain;
private int size;
private HashMap standardPropertySets;
static {
Class cls = class$jxl$write$biff$CompoundFile;
if (cls == null) {
cls = class$("jxl.write.biff.CompoundFile");
class$jxl$write$biff$CompoundFile = cls;
}
logger = Logger.getLogger(cls);
}
static Class class$(String str) {
try {
return Class.forName(str);
} catch (ClassNotFoundException e) {
throw new NoClassDefFoundError(e.getMessage());
}
}
public static final class ReadPropertyStorage {
byte[] data;
int number;
BaseCompoundFile.PropertyStorage propertyStorage;
ReadPropertyStorage(BaseCompoundFile.PropertyStorage propertyStorage, byte[] bArr, int i) {
this.propertyStorage = propertyStorage;
this.data = bArr;
this.number = i;
}
}
public CompoundFile(byte[] bArr, int i, OutputStream outputStream, jxl.read.biff.CompoundFile compoundFile) throws CopyAdditionalPropertySetsException, IOException {
this.size = i;
this.excelData = bArr;
readAdditionalPropertySets(compoundFile);
this.numRootEntryBlocks = 1;
ArrayList arrayList = this.additionalPropertySets;
this.numPropertySets = (arrayList != null ? arrayList.size() : 0) + 4;
if (this.additionalPropertySets != null) {
this.numSmallBlockDepotChainBlocks = getBigBlocksRequired(this.numSmallBlocks * 4);
this.numSmallBlockDepotBlocks = getBigBlocksRequired(this.numSmallBlocks * 64);
this.numRootEntryBlocks += getBigBlocksRequired(this.additionalPropertySets.size() * 128);
}
int bigBlocksRequired = getBigBlocksRequired(i);
if (i < 4096) {
this.requiredSize = 4096;
} else {
this.requiredSize = bigBlocksRequired * 512;
}
this.out = outputStream;
int i2 = this.requiredSize / 512;
this.excelDataBlocks = i2;
this.numBigBlockDepotBlocks = 1;
int i3 = i2 + 8 + 8 + this.additionalPropertyBlocks + this.numSmallBlockDepotBlocks + this.numSmallBlockDepotChainBlocks + this.numRootEntryBlocks;
this.numBigBlockDepotBlocks = (int) Math.ceil((i3 + 1) / 128.0d);
int ceil = (int) Math.ceil((r10 + i3) / 128.0d);
this.numBigBlockDepotBlocks = ceil;
int i4 = i3 + ceil;
if (ceil > 108) {
this.extensionBlock = 0;
this.numExtensionBlocks = (int) Math.ceil(((ceil - 109) + 1) / 127.0d);
int ceil2 = (int) Math.ceil(((r8 + i3) + this.numBigBlockDepotBlocks) / 128.0d);
this.numBigBlockDepotBlocks = ceil2;
i4 = i3 + this.numExtensionBlocks + ceil2;
} else {
this.extensionBlock = -2;
this.numExtensionBlocks = 0;
}
int i5 = this.numExtensionBlocks;
this.excelDataStartBlock = i5;
this.sbdStartBlock = -2;
if (this.additionalPropertySets != null && this.numSmallBlockDepotBlocks != 0) {
this.sbdStartBlock = this.excelDataBlocks + i5 + this.additionalPropertyBlocks + 16;
}
this.sbdStartBlockChain = -2;
int i6 = this.sbdStartBlock;
if (i6 != -2) {
this.sbdStartBlockChain = i6 + this.numSmallBlockDepotBlocks;
}
int i7 = this.sbdStartBlockChain;
if (i7 != -2) {
this.bbdStartBlock = i7 + this.numSmallBlockDepotChainBlocks;
} else {
this.bbdStartBlock = i5 + this.excelDataBlocks + this.additionalPropertyBlocks + 16;
}
int i8 = this.bbdStartBlock + this.numBigBlockDepotBlocks;
this.rootStartBlock = i8;
if (i4 != i8 + this.numRootEntryBlocks) {
logger.warn("Root start block and total blocks are inconsistent generated file may be corrupt");
Logger logger2 = logger;
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("RootStartBlock ");
stringBuffer.append(this.rootStartBlock);
stringBuffer.append(" totalBlocks ");
stringBuffer.append(i4);
logger2.warn(stringBuffer.toString());
}
}
private void readAdditionalPropertySets(jxl.read.biff.CompoundFile compoundFile) throws CopyAdditionalPropertySetsException, IOException {
boolean z;
if (compoundFile == null) {
return;
}
this.additionalPropertySets = new ArrayList();
this.standardPropertySets = new HashMap();
int numberOfPropertySets = compoundFile.getNumberOfPropertySets();
int i = 0;
for (int i2 = 0; i2 < numberOfPropertySets; i2++) {
BaseCompoundFile.PropertyStorage propertySet = compoundFile.getPropertySet(i2);
if (propertySet.name.equalsIgnoreCase(BaseCompoundFile.ROOT_ENTRY_NAME)) {
this.standardPropertySets.put(BaseCompoundFile.ROOT_ENTRY_NAME, new ReadPropertyStorage(propertySet, null, i2));
z = true;
} else {
z = false;
}
for (int i3 = 0; i3 < STANDARD_PROPERTY_SETS.length && !z; i3++) {
if (propertySet.name.equalsIgnoreCase(STANDARD_PROPERTY_SETS[i3])) {
BaseCompoundFile.PropertyStorage findPropertyStorage = compoundFile.findPropertyStorage(propertySet.name);
Assert.verify(findPropertyStorage != null);
if (findPropertyStorage == propertySet) {
this.standardPropertySets.put(STANDARD_PROPERTY_SETS[i3], new ReadPropertyStorage(propertySet, null, i2));
z = true;
}
}
}
if (!z) {
try {
byte[] stream = propertySet.size > 0 ? compoundFile.getStream(i2) : new byte[0];
this.additionalPropertySets.add(new ReadPropertyStorage(propertySet, stream, i2));
if (stream.length > 4096) {
i += getBigBlocksRequired(stream.length);
} else {
this.numSmallBlocks += getSmallBlocksRequired(stream.length);
}
} catch (BiffException e) {
logger.error(e);
throw new CopyAdditionalPropertySetsException();
}
}
}
this.additionalPropertyBlocks = i;
}
public void write() throws IOException {
writeHeader();
writeExcelData();
writeDocumentSummaryData();
writeSummaryData();
writeAdditionalPropertySets();
writeSmallBlockDepot();
writeSmallBlockDepotChain();
writeBigBlockDepot();
writePropertySets();
}
private void writeAdditionalPropertySets() throws IOException {
ArrayList arrayList = this.additionalPropertySets;
if (arrayList == null) {
return;
}
Iterator it = arrayList.iterator();
while (it.hasNext()) {
byte[] bArr = ((ReadPropertyStorage) it.next()).data;
if (bArr.length > 4096) {
int bigBlocksRequired = getBigBlocksRequired(bArr.length) * 512;
this.out.write(bArr, 0, bArr.length);
int length = bigBlocksRequired - bArr.length;
this.out.write(new byte[length], 0, length);
}
}
}
private void writeExcelData() throws IOException {
this.out.write(this.excelData, 0, this.size);
this.out.write(new byte[this.requiredSize - this.size]);
}
private void writeDocumentSummaryData() throws IOException {
this.out.write(new byte[4096]);
}
private void writeSummaryData() throws IOException {
this.out.write(new byte[4096]);
}
private void writeHeader() throws IOException {
int i;
byte[] bArr = new byte[512];
int i2 = this.numExtensionBlocks * 512;
byte[] bArr2 = new byte[i2];
System.arraycopy(IDENTIFIER, 0, bArr, 0, IDENTIFIER.length);
bArr[24] = 62;
bArr[26] = 3;
bArr[28] = -2;
bArr[29] = -1;
bArr[30] = 9;
bArr[32] = 6;
bArr[57] = UnionPtg.sid;
IntegerHelper.getFourBytes(this.numBigBlockDepotBlocks, bArr, 44);
IntegerHelper.getFourBytes(this.sbdStartBlockChain, bArr, 60);
IntegerHelper.getFourBytes(this.numSmallBlockDepotChainBlocks, bArr, 64);
IntegerHelper.getFourBytes(this.extensionBlock, bArr, 68);
IntegerHelper.getFourBytes(this.numExtensionBlocks, bArr, 72);
IntegerHelper.getFourBytes(this.rootStartBlock, bArr, 48);
int min = Math.min(this.numBigBlockDepotBlocks, 109);
int i3 = 76;
int i4 = 0;
for (int i5 = 0; i5 < min; i5++) {
IntegerHelper.getFourBytes(this.bbdStartBlock + i5, bArr, i3);
i3 += 4;
i4++;
}
while (i3 < 512) {
bArr[i3] = -1;
i3++;
}
this.out.write(bArr);
int i6 = 0;
int i7 = 0;
while (true) {
i = this.numExtensionBlocks;
if (i6 >= i) {
break;
}
int min2 = Math.min(this.numBigBlockDepotBlocks - i4, 127);
for (int i8 = 0; i8 < min2; i8++) {
IntegerHelper.getFourBytes(this.bbdStartBlock + i4 + i8, bArr2, i7);
i7 += 4;
}
i4 += min2;
IntegerHelper.getFourBytes(i4 == this.numBigBlockDepotBlocks ? -2 : i6 + 1, bArr2, i7);
i7 += 4;
i6++;
}
if (i > 0) {
while (i7 < i2) {
bArr2[i7] = -1;
i7++;
}
this.out.write(bArr2);
}
}
private void checkBbdPos() throws IOException {
if (this.bbdPos >= 512) {
this.out.write(this.bigBlockDepot);
this.bigBlockDepot = new byte[512];
this.bbdPos = 0;
}
}
private void writeBlockChain(int i, int i2) throws IOException {
int i3 = i2 - 1;
int i4 = i + 1;
while (i3 > 0) {
int min = Math.min(i3, (512 - this.bbdPos) / 4);
for (int i5 = 0; i5 < min; i5++) {
IntegerHelper.getFourBytes(i4, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
i4++;
}
i3 -= min;
checkBbdPos();
}
IntegerHelper.getFourBytes(-2, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
}
private void writeAdditionalPropertySetBlockChains() throws IOException {
ArrayList arrayList = this.additionalPropertySets;
if (arrayList == null) {
return;
}
int i = this.excelDataStartBlock + this.excelDataBlocks + 16;
Iterator it = arrayList.iterator();
while (it.hasNext()) {
ReadPropertyStorage readPropertyStorage = (ReadPropertyStorage) it.next();
if (readPropertyStorage.data.length > 4096) {
int bigBlocksRequired = getBigBlocksRequired(readPropertyStorage.data.length);
writeBlockChain(i, bigBlocksRequired);
i += bigBlocksRequired;
}
}
}
private void writeSmallBlockDepotChain() throws IOException {
if (this.sbdStartBlockChain == -2) {
return;
}
byte[] bArr = new byte[this.numSmallBlockDepotChainBlocks * 512];
Iterator it = this.additionalPropertySets.iterator();
int i = 0;
int i2 = 1;
while (it.hasNext()) {
ReadPropertyStorage readPropertyStorage = (ReadPropertyStorage) it.next();
if (readPropertyStorage.data.length <= 4096 && readPropertyStorage.data.length != 0) {
int smallBlocksRequired = getSmallBlocksRequired(readPropertyStorage.data.length);
for (int i3 = 0; i3 < smallBlocksRequired - 1; i3++) {
IntegerHelper.getFourBytes(i2, bArr, i);
i += 4;
i2++;
}
IntegerHelper.getFourBytes(-2, bArr, i);
i += 4;
i2++;
}
}
this.out.write(bArr);
}
private void writeSmallBlockDepot() throws IOException {
ArrayList arrayList = this.additionalPropertySets;
if (arrayList == null) {
return;
}
byte[] bArr = new byte[this.numSmallBlockDepotBlocks * 512];
Iterator it = arrayList.iterator();
int i = 0;
while (it.hasNext()) {
ReadPropertyStorage readPropertyStorage = (ReadPropertyStorage) it.next();
if (readPropertyStorage.data.length <= 4096) {
int smallBlocksRequired = getSmallBlocksRequired(readPropertyStorage.data.length) * 64;
System.arraycopy(readPropertyStorage.data, 0, bArr, i, readPropertyStorage.data.length);
i += smallBlocksRequired;
}
}
this.out.write(bArr);
}
private void writeBigBlockDepot() throws IOException {
this.bigBlockDepot = new byte[512];
this.bbdPos = 0;
for (int i = 0; i < this.numExtensionBlocks; i++) {
IntegerHelper.getFourBytes(-3, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
}
writeBlockChain(this.excelDataStartBlock, this.excelDataBlocks);
int i2 = this.excelDataStartBlock + this.excelDataBlocks + this.additionalPropertyBlocks;
int i3 = i2;
while (i3 < i2 + 7) {
i3++;
IntegerHelper.getFourBytes(i3, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
}
IntegerHelper.getFourBytes(-2, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
int i4 = i2 + 8;
while (i4 < i2 + 15) {
i4++;
IntegerHelper.getFourBytes(i4, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
}
IntegerHelper.getFourBytes(-2, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
writeAdditionalPropertySetBlockChains();
int i5 = this.sbdStartBlock;
if (i5 != -2) {
writeBlockChain(i5, this.numSmallBlockDepotBlocks);
writeBlockChain(this.sbdStartBlockChain, this.numSmallBlockDepotChainBlocks);
}
for (int i6 = 0; i6 < this.numBigBlockDepotBlocks; i6++) {
IntegerHelper.getFourBytes(-3, this.bigBlockDepot, this.bbdPos);
this.bbdPos += 4;
checkBbdPos();
}
writeBlockChain(this.rootStartBlock, this.numRootEntryBlocks);
int i7 = this.bbdPos;
if (i7 != 0) {
while (i7 < 512) {
this.bigBlockDepot[i7] = -1;
i7++;
}
this.out.write(this.bigBlockDepot);
}
}
private int getBigBlocksRequired(int i) {
int i2 = i / 512;
return i % 512 > 0 ? i2 + 1 : i2;
}
private int getSmallBlocksRequired(int i) {
int i2 = i / 64;
return i % 64 > 0 ? i2 + 1 : i2;
}
private void writePropertySets() throws IOException {
int[] iArr;
int i;
int i2;
int i3;
ReadPropertyStorage readPropertyStorage;
int smallBlocksRequired;
int i4 = 512;
byte[] bArr = new byte[this.numRootEntryBlocks * 512];
int i5 = 1;
if (this.additionalPropertySets != null) {
iArr = new int[this.numPropertySets];
for (int i6 = 0; i6 < STANDARD_PROPERTY_SETS.length; i6++) {
ReadPropertyStorage readPropertyStorage2 = (ReadPropertyStorage) this.standardPropertySets.get(STANDARD_PROPERTY_SETS[i6]);
if (readPropertyStorage2 != null) {
iArr[readPropertyStorage2.number] = i6;
} else {
Logger logger2 = logger;
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("Standard property set ");
stringBuffer.append(STANDARD_PROPERTY_SETS[i6]);
stringBuffer.append(" not present in source file");
logger2.warn(stringBuffer.toString());
}
}
int length = STANDARD_PROPERTY_SETS.length;
Iterator it = this.additionalPropertySets.iterator();
while (it.hasNext()) {
iArr[((ReadPropertyStorage) it.next()).number] = length;
length++;
}
} else {
iArr = null;
}
if (this.additionalPropertySets != null) {
i = (getBigBlocksRequired(this.requiredSize) * 512) + 0 + (getBigBlocksRequired(4096) * 512) + (getBigBlocksRequired(4096) * 512);
Iterator it2 = this.additionalPropertySets.iterator();
while (it2.hasNext()) {
ReadPropertyStorage readPropertyStorage3 = (ReadPropertyStorage) it2.next();
if (readPropertyStorage3.propertyStorage.type != 1) {
if (readPropertyStorage3.propertyStorage.size >= 4096) {
smallBlocksRequired = getBigBlocksRequired(readPropertyStorage3.propertyStorage.size) * 512;
} else {
smallBlocksRequired = getSmallBlocksRequired(readPropertyStorage3.propertyStorage.size) * 64;
}
i += smallBlocksRequired;
}
}
} else {
i = 0;
}
BaseCompoundFile.PropertyStorage propertyStorage = new BaseCompoundFile.PropertyStorage(BaseCompoundFile.ROOT_ENTRY_NAME);
propertyStorage.setType(5);
propertyStorage.setStartBlock(this.sbdStartBlock);
propertyStorage.setSize(i);
propertyStorage.setPrevious(-1);
propertyStorage.setNext(-1);
propertyStorage.setColour(0);
propertyStorage.setChild(this.additionalPropertySets != null ? iArr[((ReadPropertyStorage) this.standardPropertySets.get(BaseCompoundFile.ROOT_ENTRY_NAME)).propertyStorage.child] : 1);
System.arraycopy(propertyStorage.data, 0, bArr, 0, 128);
BaseCompoundFile.PropertyStorage propertyStorage2 = new BaseCompoundFile.PropertyStorage(BaseCompoundFile.WORKBOOK_NAME);
propertyStorage2.setType(2);
propertyStorage2.setStartBlock(this.excelDataStartBlock);
propertyStorage2.setSize(this.requiredSize);
int i7 = 3;
if (this.additionalPropertySets != null) {
ReadPropertyStorage readPropertyStorage4 = (ReadPropertyStorage) this.standardPropertySets.get(BaseCompoundFile.WORKBOOK_NAME);
i3 = readPropertyStorage4.propertyStorage.previous != -1 ? iArr[readPropertyStorage4.propertyStorage.previous] : -1;
i2 = readPropertyStorage4.propertyStorage.next != -1 ? iArr[readPropertyStorage4.propertyStorage.next] : -1;
} else {
i2 = -1;
i3 = 3;
}
propertyStorage2.setPrevious(i3);
propertyStorage2.setNext(i2);
propertyStorage2.setChild(-1);
System.arraycopy(propertyStorage2.data, 0, bArr, 128, 128);
BaseCompoundFile.PropertyStorage propertyStorage3 = new BaseCompoundFile.PropertyStorage("\u0005SummaryInformation");
propertyStorage3.setType(2);
propertyStorage3.setStartBlock(this.excelDataStartBlock + this.excelDataBlocks);
propertyStorage3.setSize(4096);
if (this.additionalPropertySets != null && (readPropertyStorage = (ReadPropertyStorage) this.standardPropertySets.get("\u0005SummaryInformation")) != null) {
i5 = readPropertyStorage.propertyStorage.previous != -1 ? iArr[readPropertyStorage.propertyStorage.previous] : -1;
i7 = readPropertyStorage.propertyStorage.next != -1 ? iArr[readPropertyStorage.propertyStorage.next] : -1;
}
propertyStorage3.setPrevious(i5);
propertyStorage3.setNext(i7);
propertyStorage3.setChild(-1);
System.arraycopy(propertyStorage3.data, 0, bArr, 256, 128);
BaseCompoundFile.PropertyStorage propertyStorage4 = new BaseCompoundFile.PropertyStorage("\u0005DocumentSummaryInformation");
propertyStorage4.setType(2);
propertyStorage4.setStartBlock(this.excelDataStartBlock + this.excelDataBlocks + 8);
propertyStorage4.setSize(4096);
propertyStorage4.setPrevious(-1);
propertyStorage4.setNext(-1);
propertyStorage4.setChild(-1);
System.arraycopy(propertyStorage4.data, 0, bArr, 384, 128);
ArrayList arrayList = this.additionalPropertySets;
if (arrayList == null) {
this.out.write(bArr);
return;
}
int i8 = this.excelDataStartBlock + this.excelDataBlocks + 16;
Iterator it3 = arrayList.iterator();
int i9 = 0;
while (it3.hasNext()) {
ReadPropertyStorage readPropertyStorage5 = (ReadPropertyStorage) it3.next();
int i10 = readPropertyStorage5.data.length > 4096 ? i8 : i9;
BaseCompoundFile.PropertyStorage propertyStorage5 = new BaseCompoundFile.PropertyStorage(readPropertyStorage5.propertyStorage.name);
propertyStorage5.setType(readPropertyStorage5.propertyStorage.type);
propertyStorage5.setStartBlock(i10);
propertyStorage5.setSize(readPropertyStorage5.propertyStorage.size);
int i11 = readPropertyStorage5.propertyStorage.previous != -1 ? iArr[readPropertyStorage5.propertyStorage.previous] : -1;
int i12 = readPropertyStorage5.propertyStorage.next != -1 ? iArr[readPropertyStorage5.propertyStorage.next] : -1;
int i13 = readPropertyStorage5.propertyStorage.child != -1 ? iArr[readPropertyStorage5.propertyStorage.child] : -1;
propertyStorage5.setPrevious(i11);
propertyStorage5.setNext(i12);
propertyStorage5.setChild(i13);
System.arraycopy(propertyStorage5.data, 0, bArr, i4, 128);
i4 += 128;
if (readPropertyStorage5.data.length > 4096) {
i8 += getBigBlocksRequired(readPropertyStorage5.data.length);
} else {
i9 += getSmallBlocksRequired(readPropertyStorage5.data.length);
}
}
this.out.write(bArr);
}
}