You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2016/10/13 17:06:23 UTC
commons-compress git commit: COMPRESS-327 write support for in memory
SeekableByteChannel
Repository: commons-compress
Updated Branches:
refs/heads/master e926d99b1 -> 09edbd8f1
COMPRESS-327 write support for in memory SeekableByteChannel
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/09edbd8f
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/09edbd8f
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/09edbd8f
Branch: refs/heads/master
Commit: 09edbd8f1945cd6a2ecc267f4e466862227e2355
Parents: e926d99
Author: Stefan Bodewig <bo...@apache.org>
Authored: Thu Oct 13 19:05:57 2016 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Thu Oct 13 19:05:57 2016 +0200
----------------------------------------------------------------------
.../utils/SeekableInMemoryByteChannel.java | 69 ++++++++++++++++----
.../commons/compress/archivers/ZipTestCase.java | 45 +++++++++++++
.../archivers/sevenz/SevenZOutputFileTest.java | 26 ++++++++
3 files changed, 129 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/09edbd8f/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java b/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
index ab3a606..87c2111 100644
--- a/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
+++ b/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
@@ -23,21 +23,27 @@ import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.NonWritableChannelException;
import java.nio.channels.SeekableByteChannel;
+import java.util.Arrays;
/**
* A {@link SeekableByteChannel} implementation that wraps a byte[].
+ * @since 1.13
*/
public class SeekableInMemoryByteChannel implements SeekableByteChannel {
- private final byte[] data;
+ private volatile byte[] data;
private volatile boolean closed;
- private volatile long position, size;
+ private volatile int position, size;
public SeekableInMemoryByteChannel(byte[] data) {
this.data = data;
size = data.length;
}
+ public SeekableInMemoryByteChannel() {
+ this(new byte[0]);
+ }
+
@Override
public long position() {
return position;
@@ -45,7 +51,10 @@ public class SeekableInMemoryByteChannel implements SeekableByteChannel {
@Override
public SeekableByteChannel position(long newPosition) {
- position = newPosition;
+ if (newPosition > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Position cannot exceed " + Integer.MAX_VALUE);
+ }
+ position = (int) newPosition;
return this;
}
@@ -56,7 +65,12 @@ public class SeekableInMemoryByteChannel implements SeekableByteChannel {
@Override
public SeekableByteChannel truncate(long newSize) {
- size = newSize;
+ if (size > newSize) {
+ size = (int) newSize;
+ }
+ if (position > size) {
+ position = size;
+ }
return this;
}
@@ -65,14 +79,14 @@ public class SeekableInMemoryByteChannel implements SeekableByteChannel {
if (!isOpen()) {
throw new ClosedChannelException();
}
- long pos = position;
- long sz = size;
+ int pos = position;
+ int sz = size;
int wanted = buf.remaining();
- long possible = sz - pos;
+ int possible = sz - pos;
if (wanted > possible) {
- wanted = (int) possible;
+ wanted = possible;
}
- buf.put(data, (int) pos, wanted);
+ buf.put(data, pos, wanted);
position = pos + wanted;
return wanted;
}
@@ -87,9 +101,42 @@ public class SeekableInMemoryByteChannel implements SeekableByteChannel {
return !closed;
}
- // TODO implement writing
@Override
public int write(ByteBuffer b) throws IOException {
- throw new NonWritableChannelException();
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ int pos = position;
+ int sz = data.length;
+ int wanted = b.remaining();
+ int possibleWithoutResize = sz - pos;
+ if (wanted > possibleWithoutResize) {
+ resize(pos + wanted);
+ }
+ b.get(data, pos, wanted);
+ position = pos + wanted;
+ if (size < position) {
+ size = position;
+ }
+ return wanted;
}
+
+ /**
+ * Obtains the array backing this channel.
+ */
+ public byte[] array() {
+ return data;
+ }
+
+ private void resize(int newLength) {
+ int len = data.length;
+ if (len <= 0) {
+ len = 1;
+ }
+ while (len < newLength) {
+ len <<= 1;
+ }
+ data = Arrays.copyOf(data, len);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/09edbd8f/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java b/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
index 00015ad..84297ae 100644
--- a/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
+++ b/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
@@ -41,6 +41,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.archivers.zip.ZipMethod;
import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
import org.junit.Assert;
import org.junit.Test;
@@ -109,6 +110,50 @@ public final class ZipTestCase extends AbstractTestCase {
}
/**
+ * Archives 2 files and unarchives it again. If the file length of result
+ * and source is the same, it looks like the operations have worked
+ * @throws Exception
+ */
+ @Test
+ public void testZipArchiveCreationInMemory() throws Exception {
+ final File file1 = getFile("test1.xml");
+ final File file2 = getFile("test2.xml");
+ SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
+ try (ZipArchiveOutputStream os = new ZipArchiveOutputStream(c)) {
+ os.putArchiveEntry(new ZipArchiveEntry("testdata/test1.xml"));
+ IOUtils.copy(new FileInputStream(file1), os);
+ os.closeArchiveEntry();
+
+ os.putArchiveEntry(new ZipArchiveEntry("testdata/test2.xml"));
+ IOUtils.copy(new FileInputStream(file2), os);
+ os.closeArchiveEntry();
+ }
+
+ // Unarchive the same
+ final List<File> results = new ArrayList<>();
+
+ try (ArchiveInputStream in = new ArchiveStreamFactory()
+ .createArchiveInputStream("zip", new ByteArrayInputStream(c.array()))) {
+
+ ZipArchiveEntry entry = null;
+ while((entry = (ZipArchiveEntry)in.getNextEntry()) != null) {
+ final File outfile = new File(resultDir.getCanonicalPath() + "/result/" + entry.getName());
+ outfile.getParentFile().mkdirs();
+ try (OutputStream o = new FileOutputStream(outfile)) {
+ IOUtils.copy(in, o);
+ }
+ results.add(outfile);
+ }
+ }
+
+ assertEquals(results.size(), 2);
+ File result = results.get(0);
+ assertEquals(file1.length(), result.length());
+ result = results.get(1);
+ assertEquals(file2.length(), result.length());
+ }
+
+ /**
* Simple unarchive test. Asserts nothing.
* @throws Exception
*/
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/09edbd8f/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
index 989aa4d..aee1e02 100644
--- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
@@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import org.apache.commons.compress.AbstractTestCase;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
import org.tukaani.xz.LZMA2Options;
public class SevenZOutputFileTest extends AbstractTestCase {
@@ -301,6 +302,16 @@ public class SevenZOutputFileTest extends AbstractTestCase {
}
@Test
+ public void testStackOfContentCompressionsInMemory() throws Exception {
+ final ArrayList<SevenZMethodConfiguration> methods = new ArrayList<>();
+ methods.add(new SevenZMethodConfiguration(SevenZMethod.LZMA2));
+ methods.add(new SevenZMethodConfiguration(SevenZMethod.COPY));
+ methods.add(new SevenZMethodConfiguration(SevenZMethod.DEFLATE));
+ methods.add(new SevenZMethodConfiguration(SevenZMethod.BZIP2));
+ createAndReadBack(new SeekableInMemoryByteChannel(), methods);
+ }
+
+ @Test
public void testDeflateWithConfiguration() throws Exception {
output = new File(dir, "deflate-options.7z");
// Deflater.BEST_SPEED
@@ -464,6 +475,21 @@ public class SevenZOutputFileTest extends AbstractTestCase {
}
}
+ private void createAndReadBack(final SeekableInMemoryByteChannel output, final Iterable<SevenZMethodConfiguration> methods) throws Exception {
+ final SevenZOutputFile outArchive = new SevenZOutputFile(output);
+ outArchive.setContentMethods(methods);
+ try {
+ addFile(outArchive, 0, true);
+ } finally {
+ outArchive.close();
+ }
+ try (SevenZFile archive =
+ new SevenZFile(new SeekableInMemoryByteChannel(output.array()), "in memory",
+ null)) {
+ assertEquals(Boolean.TRUE, verifyFile(archive, 0, methods));
+ }
+ }
+
private static void assertContentMethodsEquals(final Iterable<? extends SevenZMethodConfiguration> expected,
final Iterable<? extends SevenZMethodConfiguration> actual) {
assertNotNull(actual);