110 lines
3.4 KiB
Java
110 lines
3.4 KiB
Java
package net.filebot.archive;
|
|
|
|
import java.io.Closeable;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.RandomAccessFile;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
import net.sf.sevenzipjbinding.IArchiveOpenCallback;
|
|
import net.sf.sevenzipjbinding.IArchiveOpenVolumeCallback;
|
|
import net.sf.sevenzipjbinding.IInStream;
|
|
import net.sf.sevenzipjbinding.PropID;
|
|
import net.sf.sevenzipjbinding.SevenZipException;
|
|
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
|
|
|
class ArchiveOpenVolumeCallback implements IArchiveOpenVolumeCallback, IArchiveOpenCallback, Closeable {
|
|
|
|
/**
|
|
* Cache for opened file streams
|
|
*/
|
|
private Map<String, RandomAccessFile> openedRandomAccessFileList = new HashMap<String, RandomAccessFile>();
|
|
|
|
/**
|
|
* Name of the last volume returned by {@link #getStream(String)}
|
|
*/
|
|
private String name;
|
|
|
|
/**
|
|
* This method should at least provide the name of the last opened volume (propID=PropID.NAME).
|
|
*
|
|
* @see IArchiveOpenVolumeCallback#getProperty(PropID)
|
|
*/
|
|
@Override
|
|
public Object getProperty(PropID propID) throws SevenZipException {
|
|
switch (propID) {
|
|
case NAME:
|
|
return name;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The name of the required volume will be calculated out of the name of the first volume and a volume index. In case of RAR file, the substring ".partNN." in the name of the volume file will indicate a volume with id NN. For example:
|
|
* <ul>
|
|
* <li>test.rar - single part archive or multi-part archive with a single volume</li>
|
|
* <li>test.part23.rar - 23-th part of a multi-part archive</li>
|
|
* <li>test.part001.rar - first part of a multi-part archive. "00" indicates, that at least 100 volumes must exist.</li>
|
|
* </ul>
|
|
*/
|
|
@Override
|
|
public IInStream getStream(String filename) throws SevenZipException {
|
|
try {
|
|
// We use caching of opened streams, so check cache first
|
|
RandomAccessFile randomAccessFile = openedRandomAccessFileList.get(filename);
|
|
if (randomAccessFile != null) { // Cache hit.
|
|
// Move the file pointer back to the beginning
|
|
// in order to emulating new stream
|
|
randomAccessFile.seek(0);
|
|
|
|
// Save current volume name in case getProperty() will be called
|
|
name = filename;
|
|
|
|
return new RandomAccessFileInStream(randomAccessFile);
|
|
}
|
|
|
|
// Nothing useful in cache. Open required volume.
|
|
randomAccessFile = new RandomAccessFile(filename, "r");
|
|
|
|
// Put new stream in the cache
|
|
openedRandomAccessFileList.put(filename, randomAccessFile);
|
|
|
|
// Save current volume name in case getProperty() will be called
|
|
name = filename;
|
|
return new RandomAccessFileInStream(randomAccessFile);
|
|
} catch (FileNotFoundException fileNotFoundException) {
|
|
// Required volume doesn't exist. This happens if the volume:
|
|
// 1. never exists. 7-Zip doesn't know how many volumes should
|
|
// exist, so it have to try each volume.
|
|
// 2. should be there, but doesn't. This is an error case.
|
|
|
|
// Since normal and error cases are possible,
|
|
// we can't throw an error message
|
|
return null; // We return always null in this case
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close all opened streams
|
|
*/
|
|
@Override
|
|
public void close() throws IOException {
|
|
for (RandomAccessFile file : openedRandomAccessFileList.values()) {
|
|
file.close();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setCompleted(Long files, Long bytes) throws SevenZipException {
|
|
}
|
|
|
|
@Override
|
|
public void setTotal(Long files, Long bytes) throws SevenZipException {
|
|
}
|
|
|
|
}
|