filebot/source/net/filebot/archive/ArchiveOpenVolumeCallback.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 {
}
}