package SevenZip.Archive.SevenZip; import java.io.IOException; import java.io.OutputStream; import SevenZip.Archive.Common.OutStreamWithCRC; import SevenZip.Archive.IArchiveExtractCallback; import SevenZip.Archive.IInArchive; import Common.BoolVector; public class FolderOutStream extends OutputStream { private OutStreamWithCRC outStreamWithHashSpec; private ArchiveDB archiveDatabase; private BoolVector extractStatuses; private int startIndex; private int ref2Offset; private IArchiveExtractCallback extractCallback; private boolean testMode; private int currentIndex; private boolean fileIsOpen; private long filePos; public FolderOutStream( ArchiveDB archiveDatabase, int ref2Offset, int startIndex, BoolVector extractStatuses, IArchiveExtractCallback extractCallback, boolean testMode) throws IOException { this(new OutStreamWithCRC(), archiveDatabase, ref2Offset, startIndex, extractStatuses, extractCallback, testMode); } public FolderOutStream(OutStreamWithCRC os, ArchiveDB archiveDatabase, int ref2Offset, int startIndex, BoolVector extractStatuses, IArchiveExtractCallback extractCallback, boolean testMode) throws IOException { if (os == null) throw new NullPointerException(); this.outStreamWithHashSpec = os; this.archiveDatabase = archiveDatabase; this.ref2Offset = ref2Offset; this.startIndex = startIndex; this.extractStatuses = extractStatuses; this.extractCallback = extractCallback; this.testMode = testMode; this.currentIndex = 0; this.fileIsOpen = false; WriteEmptyFiles(); } private void OpenFile() throws IOException { int askMode; if (this.extractStatuses.get(this.currentIndex)) { askMode = this.testMode ? IInArchive.NExtract_NAskMode_kTest : IInArchive.NExtract_NAskMode_kExtract; } else { askMode = IInArchive.NExtract_NAskMode_kSkip; } int index = this.startIndex + this.currentIndex; OutputStream realOutStream = this.extractCallback.GetStream(this.ref2Offset + index, askMode); this.outStreamWithHashSpec.setStream(realOutStream); this.outStreamWithHashSpec.reset(); if (realOutStream == null && askMode == IInArchive.NExtract_NAskMode_kExtract) { FileItem fileInfo = (FileItem)this.archiveDatabase.Files.get(index); if (!fileInfo.IsAnti && !fileInfo.IsDirectory) askMode = IInArchive.NExtract_NAskMode_kSkip; } this.extractCallback.PrepareOperation(askMode); } private int WriteEmptyFiles() throws IOException { int begin = this.currentIndex; for(;this.currentIndex < this.extractStatuses.size(); this.currentIndex++) { int index = this.startIndex + this.currentIndex; FileItem fileInfo = (FileItem)this.archiveDatabase.Files.get(index); if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0) return -1; // return HRESULT.S_OK; OpenFile(); this.extractCallback.SetOperationResult(IInArchive.NExtract_NOperationResult_kOK); this.outStreamWithHashSpec.releaseStream(); } return this.extractStatuses.size() - begin; } public void write(int b) throws IOException { throw new IOException("FolderOutStream - write() not implemented"); } public void /* UInt32 *processedSize */ write(byte[] data, int off, int size) throws IOException { int realProcessedSize = 0; while(this.currentIndex < this.extractStatuses.size()) { if (this.fileIsOpen) { int index = this.startIndex + this.currentIndex; FileItem fileInfo = (FileItem)this.archiveDatabase.Files.get(index); long fileSize = fileInfo.UnPackSize; long numBytesToWrite2 = fileSize - this.filePos; int tmp = size - realProcessedSize; if (tmp < numBytesToWrite2) numBytesToWrite2 = tmp; int processedSizeLocal; // int res = _outStreamWithHash.Write((const Byte *)data + realProcessedSize,numBytesToWrite, &processedSizeLocal)); // if (res != HRESULT.S_OK) throw new java.io.IOException("_outStreamWithHash.Write : " + res); // return res; processedSizeLocal = (int)numBytesToWrite2; this.outStreamWithHashSpec.write(data, realProcessedSize + off, (int)numBytesToWrite2); this.filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (this.filePos == fileSize) { boolean digestsAreEqual = !fileInfo.IsFileCRCDefined || (fileInfo.FileCRC == this.outStreamWithHashSpec.getCRC()); this.extractCallback.SetOperationResult(digestsAreEqual ? IInArchive.NExtract_NOperationResult_kOK : IInArchive.NExtract_NOperationResult_kCRCError); this.outStreamWithHashSpec.releaseStream(); this.fileIsOpen = false; this.currentIndex++; } if (realProcessedSize == size) { WriteEmptyFiles(); return ;// return realProcessedSize; } } else { OpenFile(); this.fileIsOpen = true; this.filePos = 0; } } } public void FlushCorrupted(int resultEOperationResult) throws IOException { while(this.currentIndex < this.extractStatuses.size()) { if (this.fileIsOpen) { this.extractCallback.SetOperationResult(resultEOperationResult); this.outStreamWithHashSpec.releaseStream(); this.fileIsOpen = false; this.currentIndex++; } else { OpenFile(); this.fileIsOpen = true; } } } public boolean IsWritingFinished() { return this.currentIndex == this.extractStatuses.size(); } }