Skip to content

Commit

Permalink
feat: multi-part extraction from inputstream
Browse files Browse the repository at this point in the history
closes #52
  • Loading branch information
gotson committed Jul 27, 2020
1 parent e1403ff commit 9ee32ea
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/github/junrar/Archive.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public Archive(
this.password = password;

try {
setVolume(this.volumeManager.nextArchive(this, null));
setVolume(this.volumeManager.nextVolume(this, null));
} catch (IOException | RarException e) {
try {
close();
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/github/junrar/Junrar.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
import com.github.junrar.volume.VolumeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -52,6 +53,22 @@ public static List<File> extract(final InputStream resourceAsStream, final File
return extractArchiveTo(arch, lfe);
}

public static List<File> extract(final VolumeManager volumeManager, final File destinationFolder) throws IOException, RarException {
validateDestinationPath(destinationFolder);

final Archive arch = createArchiveOrThrowException(volumeManager, null);
LocalFolderExtractor lfe = new LocalFolderExtractor(destinationFolder);
return extractArchiveTo(arch, lfe);
}

public static List<File> extract(final VolumeManager volumeManager, final File destinationFolder, final String password) throws IOException, RarException {
validateDestinationPath(destinationFolder);

final Archive arch = createArchiveOrThrowException(volumeManager, password);
LocalFolderExtractor lfe = new LocalFolderExtractor(destinationFolder);
return extractArchiveTo(arch, lfe);
}


public static List<ContentDescription> getContentsDescription(final File rar) throws RarException, IOException {
validateRarPath(rar);
Expand All @@ -73,6 +90,15 @@ public static List<ContentDescription> getContentsDescription(final File rar) th
return contents;
}

private static Archive createArchiveOrThrowException(final VolumeManager volumeManager, final String password) throws RarException, IOException {
try {
return new Archive(volumeManager, null, password);
} catch (final RarException | IOException e) {
Junrar.logger.error("Error while creating archive", e);
throw e;
}
}

private static Archive createArchiveOrThrowException(final InputStream rarAsStream, final String password) throws RarException, IOException {
try {
return new Archive(rarAsStream, password);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/github/junrar/unpack/ComprDataIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public int unpRead(byte[] addr, int offset, int count) throws IOException, RarEx
archive.bytesReadRead(retCode);

if (unpPackedSize == 0 && subHead.isSplitAfter()) {
Volume nextVolume = archive.getVolumeManager().nextArchive(archive, archive.getVolume());
Volume nextVolume = archive.getVolumeManager().nextVolume(archive, archive.getVolume());
if (nextVolume == null) {
nextVolumeMissing = true;
return -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public FileVolumeManager(final File firstVolume) {
}

@Override
public Volume nextArchive(final Archive archive, final Volume last) {
public Volume nextVolume(final Archive archive, final Volume last) {
if (last == null) return new FileVolume(archive, this.firstVolume);

final FileVolume lastFileVolume = (FileVolume) last;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ public class InputStreamVolume implements Volume {

private final Archive archive;
private final InputStream inputStream;
private final int position;

public InputStreamVolume(final Archive archive, final InputStream inputStream) {
public InputStreamVolume(final Archive archive, final InputStream inputStream, final int position) {
this.archive = archive;
this.inputStream = inputStream;
this.position = position;
}

@Override
Expand All @@ -31,4 +33,7 @@ public Archive getArchive() {
return this.archive;
}

public int getPosition() {
return position;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,33 @@
import com.github.junrar.Archive;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class InputStreamVolumeManager implements VolumeManager {

private final InputStream is;
private final Map<Integer, InputStream> streams = new HashMap<>();

public InputStreamVolumeManager(final InputStream is) {
this.is = is;
streams.put(1, is);
}

public InputStreamVolumeManager(List<InputStream> streams) {
for (int i = 0; i < streams.size(); i++) {
this.streams.put(i + 1, streams.get(i));
}
}

@Override
public Volume nextArchive(final Archive archive, final Volume lastVolume) {
return new InputStreamVolume(archive, this.is);
public Volume nextVolume(final Archive archive, final Volume lastVolume) {
if (lastVolume == null) return new InputStreamVolume(archive, streams.get(1), 1);

InputStreamVolume lastStreamVolume = (InputStreamVolume) lastVolume;
int nextPosition = lastStreamVolume.getPosition() + 1;
InputStream next = streams.get(nextPosition);
if (next != null) return new InputStreamVolume(archive, next, nextPosition);
return null;
}

}
10 changes: 9 additions & 1 deletion src/main/java/com/github/junrar/volume/VolumeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface VolumeManager {
Volume nextArchive(Archive archive, Volume lastVolume) throws IOException;
/**
* Returns either the first volume or the next volume.
*
* @param archive the archive the volumes are part of
* @param lastVolume the last volume before the one to return
* @return the first volume if lastVolume is null, else the next volume after lastVolume
* @throws IOException if the volume cannot be read
*/
Volume nextVolume(Archive archive, Volume lastVolume) throws IOException;
}
33 changes: 33 additions & 0 deletions src/test/java/com/github/junrar/VolumeExtractorTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.junrar;

import com.github.junrar.exception.RarException;
import com.github.junrar.volume.InputStreamVolumeManager;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -9,9 +10,15 @@
import org.junit.jupiter.params.provider.MethodSource;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -45,6 +52,32 @@ public void extractionFromVolumedFile(String ressourceDir, String firstVolume) t
checkContent(unpackedDir);
}

@ParameterizedTest
@MethodSource("volumeArgs")
public void extractionFromVolumedStream(String ressourceDir, String firstVolume) throws Exception {
File dir = new File(getClass().getResource(ressourceDir).getPath());
TestCommons.copyRarsToFolder(tempFolder, dir);

List<File> files = Arrays.stream(tempFolder.listFiles())
.filter(File::isFile)
.sorted()
.collect(Collectors.toList());
System.out.println(files);

List<InputStream> streams = new ArrayList<>();
for (File f : files) {
streams.add(new FileInputStream(f));
}

final File unpackedDir = new File(tempFolder, "test-documents");
unpackedDir.delete();
unpackedDir.mkdir();

Junrar.extract(new InputStreamVolumeManager(streams), unpackedDir);

checkContent(unpackedDir);
}

private static Stream<Arguments> volumeArgs() {
return Stream.of(
Arguments.of("volumes/new-numbers", "test-documents.000.rar"),
Expand Down

0 comments on commit 9ee32ea

Please sign in to comment.