package SevenZip.Archive.SevenZip;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import SevenZip.HRESULT;
import SevenZip.IInStream;
import SevenZip.MyRandomAccessFile;
import SevenZip.ICompressProgressInfo;
import SevenZip.Common.LocalProgress;
import SevenZip.Common.LocalCompressProgressInfo;
import SevenZip.Archive.IInArchive;
import SevenZip.Archive.IArchiveExtractCallback;
import SevenZip.Archive.SevenZipEntry;
public class Handler implements IInArchive {
public IInStream _inStream;
public ArchiveDB _database;
int _numThreads = 1; // XXX: configurable
public Handler(File archive) throws IOException {
this(new MyRandomAccessFile(archive, "r"), kMaxCheckStartPosition);
}
public Handler(IInStream stream) throws IOException {
this(stream, kMaxCheckStartPosition);
}
public Handler(IInStream stream, long maxCheckStartPosition) throws IOException {
InStream archive = new InStream(stream, maxCheckStartPosition);
this._database = new ArchiveDB(archive);
this._inStream = stream;
}
public void Extract(int [] indices, int numItems,
int testModeSpec, IArchiveExtractCallback extractCallback) throws IOException {
boolean testMode = (testModeSpec != 0);
long importantTotalUnPacked = 0;
boolean allFilesMode = (numItems == -1);
if (allFilesMode)
numItems = this._database.Files.size();
if (numItems == 0)
return;
Vector<ExtractFolderInfo> extractFolderInfoVector = new Vector();
for (int ii = 0; ii < numItems; ii++) {
int ref2Index = allFilesMode ? ii : indices[ii];
ArchiveDB database = _database;
int fileIndex = ref2Index;
int folderIndex = database.FileIndexToFolderIndexMap.get(fileIndex);
if (folderIndex == ArchiveDB.kNumNoIndex) {
extractFolderInfoVector.add( new ExtractFolderInfo(fileIndex, ArchiveDB.kNumNoIndex));
continue;
}
if (extractFolderInfoVector.isEmpty() ||
folderIndex != (extractFolderInfoVector.lastElement()).FolderIndex) {
extractFolderInfoVector.add(new ExtractFolderInfo(ArchiveDB.kNumNoIndex, folderIndex));
Folder folderInfo = database.Folders.get(folderIndex);
long unPackSize = folderInfo.GetUnPackSize();
importantTotalUnPacked += unPackSize;
extractFolderInfoVector.lastElement().UnPackSize = unPackSize;
}
ExtractFolderInfo efi = extractFolderInfoVector.lastElement();
int startIndex = database.FolderStartFileIndex.get(folderIndex); // CNum
for (int index = efi.ExtractStatuses.size(); index <= fileIndex - startIndex; index++)
efi.ExtractStatuses.add(index == fileIndex - startIndex);
}
extractCallback.SetTotal(importantTotalUnPacked);
Decoder decoder = new Decoder(false);
long currentImportantTotalUnPacked = 0;
long totalFolderUnPacked;
for (int i = 0; i < extractFolderInfoVector.size(); i++, currentImportantTotalUnPacked += totalFolderUnPacked) {
ExtractFolderInfo efi = extractFolderInfoVector.get(i);
totalFolderUnPacked = efi.UnPackSize;
extractCallback.SetCompleted(currentImportantTotalUnPacked);
int startIndex; // CNum
if (efi.FileIndex != ArchiveDB.kNumNoIndex)
startIndex = efi.FileIndex;
else
startIndex = this._database.FolderStartFileIndex.get(efi.FolderIndex);
FolderOutStream folderOutStream = new FolderOutStream(this._database, 0, startIndex, efi.ExtractStatuses, extractCallback, testMode);
int result = HRESULT.S_OK;
if (efi.FileIndex != ArchiveDB.kNumNoIndex)
continue;
int folderIndex = efi.FolderIndex; // CNum
Folder folderInfo = this._database.Folders.get(folderIndex);
LocalProgress localProgressSpec = new LocalProgress(extractCallback, false);
ICompressProgressInfo compressProgress = new LocalCompressProgressInfo(
localProgressSpec,
ICompressProgressInfo.INVALID,
currentImportantTotalUnPacked);
int packStreamIndex = this._database.FolderStartPackStreamIndex.get(folderIndex); // CNum
long folderStartPackPos = this._database.GetFolderStreamPos(folderIndex, 0);
try {
/* TODO: result = */ decoder.Decode(
this._inStream,
folderStartPackPos,
this._database.PackSizes,
packStreamIndex,
folderInfo,
folderOutStream,
compressProgress);
if (result == HRESULT.S_FALSE) {
folderOutStream.FlushCorrupted(IInArchive.NExtract_NOperationResult_kDataError);
// if (result != HRESULT.S_OK) return result;
continue;
}
if (result == HRESULT.E_NOTIMPL) {
folderOutStream.FlushCorrupted(IInArchive.NExtract_NOperationResult_kUnSupportedMethod);
// if (result != HRESULT.S_OK) return result;
continue;
}
if (folderOutStream.IsWritingFinished()) {
folderOutStream.FlushCorrupted(IInArchive.NExtract_NOperationResult_kDataError);
// if (result != HRESULT.S_OK) return result;
continue;
}
} catch(Exception e) {
System.out.println("IOException : " + e);
e.printStackTrace();
folderOutStream.FlushCorrupted(IInArchive.NExtract_NOperationResult_kDataError);
// if (result != HRESULT.S_OK) return result;
continue;
}
}
}
protected void finalize() throws Throwable {
close();
super.finalize();
}
public void close() throws IOException {
if (_inStream != null) _inStream.close();
_inStream = null;
_database.clear();
}
public int size() {
return _database.Files.size();
}
private long getPackSize(int index2) {
long packSize = 0;
int folderIndex = _database.FileIndexToFolderIndexMap.get(index2);
if (folderIndex != ArchiveDB.kNumNoIndex) {
if (_database.FolderStartFileIndex.get(folderIndex) == index2)
packSize = _database.GetFolderFullPackSize(folderIndex);
}
return packSize;
}
private static int GetUInt32FromMemLE(byte [] p , int off) {
return p[off]
| (((int)p[off + 1]) << 8)
| (((int)p[off + 2]) << 16)
| (((int)p[off + 3]) << 24);
}
private static String GetStringForSizeValue(int value) {
for (int i = 31; i >= 0; i--)
if ((1 << i) == value)
return Integer.toString(i);
StringBuffer result = new StringBuffer();
if (value % (1 << 20) == 0) {
result.append(value >> 20);
result.append('m');
} else if (value % (1 << 10) == 0) {
result.append(value >> 10);
result.append('k');
} else {
result.append(value);
result.append('b');
}
return result.toString();
}
private String getMethods(int index2) {
int folderIndex = _database.FileIndexToFolderIndexMap.get(index2);
if (folderIndex != ArchiveDB.kNumNoIndex) {
Folder folderInfo = _database.Folders.get(folderIndex);
StringBuffer methodsString = new StringBuffer();
for (int i = folderInfo.Coders.size() - 1; i >= 0; i--) {
CoderInfo coderInfo = folderInfo.Coders.get(i);
if (methodsString.length() > 0)
methodsString.append(' ');
// MethodInfo methodInfo;
for (int j = 0; j < coderInfo.AltCoders.size(); j++) {
if (j > 0) methodsString.append('|');
AltCoderInfo altCoderInfo = (AltCoderInfo)coderInfo.AltCoders.get(j);
if (altCoderInfo.MethodID.getName() == null) {
// TBD methodsString += altCoderInfo.MethodID.ConvertToString();
} else {
methodsString.append(altCoderInfo.MethodID.getName());
if (altCoderInfo.MethodID.equals(MethodID.k_LZMA)) {
if (altCoderInfo.Properties.size() >= 5) {
methodsString.append(':');
int dicSize = GetUInt32FromMemLE(altCoderInfo.Properties.toByteArray(), 1);
methodsString.append(GetStringForSizeValue(dicSize));
}
}
/* else if (altCoderInfo.MethodID == k_PPMD) {
if (altCoderInfo.Properties.GetCapacity() >= 5) {
Byte order = *(const Byte *)altCoderInfo.Properties;
methodsString += ":o";
methodsString += ConvertUInt32ToString(order);
methodsString += ":mem";
UInt32 dicSize = GetUInt32FromMemLE(
((const Byte *)altCoderInfo.Properties + 1));
methodsString += GetStringForSizeValue(dicSize);
}
} else if (altCoderInfo.MethodID == k_AES) {
if (altCoderInfo.Properties.GetCapacity() >= 1) {
methodsString += ":";
const Byte *data = (const Byte *)altCoderInfo.Properties;
Byte firstByte = *data++;
UInt32 numCyclesPower = firstByte & 0x3F;
methodsString += ConvertUInt32ToString(numCyclesPower);
}
} else {
if (altCoderInfo.Properties.GetCapacity() > 0) {
methodsString += ":[";
for (size_t bi = 0; bi < altCoderInfo.Properties.GetCapacity(); bi++) {
if (bi > 5 && bi + 1 < altCoderInfo.Properties.GetCapacity()) {
methodsString += "..";
break;
} else
methodsString += GetHex2(altCoderInfo.Properties[bi]);
}
methodsString += "]";
}
}
*/
}
}
}
return methodsString.toString();
}
return new String();
}
public SevenZipEntry getEntry(int index) {
SevenZip.Archive.SevenZip.FileItem item = (FileItem)_database.Files.get(index);
return new SevenZipEntry(
item.name,
getPackSize(index),
item.UnPackSize,
(item.IsFileCRCDefined) ? item.FileCRC & 0xFFFFFFFFL : -1,
item.LastWriteTime,
(item.IsStartPosDefined) ? item.StartPos : -1,
item.IsDirectory,
item.Attributes,
getMethods(index));
}
}