177 lines
4.6 KiB
Java
177 lines
4.6 KiB
Java
|
|
package net.sourceforge.filebot.archive;
|
|
|
|
|
|
import java.io.Closeable;
|
|
import java.io.File;
|
|
import java.io.FileFilter;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.util.ArrayList;
|
|
import java.util.EnumMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Scanner;
|
|
import java.util.Set;
|
|
import java.util.TreeSet;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import net.sf.sevenzipjbinding.ArchiveFormat;
|
|
import net.sf.sevenzipjbinding.ISevenZipInArchive;
|
|
import net.sf.sevenzipjbinding.PropID;
|
|
import net.sf.sevenzipjbinding.SevenZipException;
|
|
import net.sourceforge.filebot.MediaTypes;
|
|
import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter;
|
|
|
|
|
|
public class Archive implements Closeable {
|
|
|
|
private ISevenZipInArchive inArchive;
|
|
private ArchiveOpenVolumeCallback openVolume;
|
|
|
|
|
|
public Archive(File file) throws Exception {
|
|
// initialize 7-Zip-JBinding
|
|
if (!file.exists()) {
|
|
throw new FileNotFoundException(file.getAbsolutePath());
|
|
}
|
|
|
|
try {
|
|
openVolume = new ArchiveOpenVolumeCallback();
|
|
if (!hasMultiPartIndex(file)) {
|
|
// single volume archives and multi-volume rar archives
|
|
inArchive = SevenZipLoader.open(openVolume.getStream(file.getAbsolutePath()), openVolume);
|
|
} else {
|
|
// raw multi-volume archives
|
|
inArchive = SevenZipLoader.open(new VolumedArchiveInStream(file.getAbsolutePath(), openVolume), null);
|
|
}
|
|
} catch (InvocationTargetException e) {
|
|
throw (Exception) e.getTargetException();
|
|
}
|
|
}
|
|
|
|
|
|
public int itemCount() throws SevenZipException {
|
|
return inArchive.getNumberOfItems();
|
|
}
|
|
|
|
|
|
public Map<PropID, Object> getItem(int index) throws SevenZipException {
|
|
Map<PropID, Object> item = new EnumMap<PropID, Object>(PropID.class);
|
|
|
|
for (PropID prop : PropID.values()) {
|
|
Object value = inArchive.getProperty(index, prop);
|
|
if (value != null) {
|
|
item.put(prop, value);
|
|
}
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
|
|
public List<File> listFiles() throws SevenZipException {
|
|
List<File> paths = new ArrayList<File>();
|
|
|
|
for (int i = 0; i < inArchive.getNumberOfItems(); i++) {
|
|
boolean isFolder = (Boolean) inArchive.getProperty(i, PropID.IS_FOLDER);
|
|
if (!isFolder) {
|
|
String path = (String) inArchive.getProperty(i, PropID.PATH);
|
|
if (path != null) {
|
|
paths.add(new File(path));
|
|
}
|
|
}
|
|
}
|
|
|
|
return paths;
|
|
}
|
|
|
|
|
|
public void extract(ExtractOutProvider outputMapper) throws SevenZipException {
|
|
inArchive.extract(null, false, new ExtractCallback(inArchive, outputMapper));
|
|
}
|
|
|
|
|
|
public void extract(ExtractOutProvider outputMapper, FileFilter filter) throws SevenZipException {
|
|
List<Integer> selection = new ArrayList<Integer>();
|
|
|
|
for (int i = 0; i < inArchive.getNumberOfItems(); i++) {
|
|
boolean isFolder = (Boolean) inArchive.getProperty(i, PropID.IS_FOLDER);
|
|
if (!isFolder) {
|
|
String path = (String) inArchive.getProperty(i, PropID.PATH);
|
|
if (path != null && filter.accept(new File(path))) {
|
|
selection.add(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
int[] indices = new int[selection.size()];
|
|
for (int i = 0; i < indices.length; i++) {
|
|
indices[i] = selection.get(i);
|
|
}
|
|
inArchive.extract(indices, false, new ExtractCallback(inArchive, outputMapper));
|
|
}
|
|
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
try {
|
|
inArchive.close();
|
|
} catch (SevenZipException e) {
|
|
throw new IOException(e);
|
|
} finally {
|
|
openVolume.close();
|
|
}
|
|
}
|
|
|
|
|
|
public static Set<String> getArchiveTypes() {
|
|
Set<String> extensions = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
|
|
|
|
// application data
|
|
extensions.addAll(MediaTypes.getDefault().getExtensionList("archive"));
|
|
|
|
// formats provided by the library
|
|
for (ArchiveFormat it : ArchiveFormat.values()) {
|
|
extensions.add(it.getMethodName());
|
|
}
|
|
|
|
return extensions;
|
|
}
|
|
|
|
private static final Pattern multiPartIndex = Pattern.compile("[.][0-9]{3}+$");
|
|
|
|
|
|
public static boolean hasMultiPartIndex(File file) {
|
|
return multiPartIndex.matcher(file.getName()).find();
|
|
}
|
|
|
|
public static final FileFilter VOLUME_ONE_FILTER = new FileFilter() {
|
|
|
|
private Pattern volume = Pattern.compile("[.]r[0-9]+$|[.]part[0-9]+|[.][0-9]+$", Pattern.CASE_INSENSITIVE);
|
|
private FileFilter archives = new ExtensionFileFilter(getArchiveTypes());
|
|
|
|
|
|
@Override
|
|
public boolean accept(File path) {
|
|
if (!archives.accept(path) && !hasMultiPartIndex(path)) {
|
|
return false;
|
|
}
|
|
|
|
Matcher matcher = volume.matcher(path.getName());
|
|
if (matcher.find()) {
|
|
Scanner scanner = new Scanner(matcher.group()).useDelimiter("\\D+");
|
|
if (!scanner.hasNext() || scanner.nextInt() != 1) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
};
|
|
|
|
}
|