[jboss-cvs] JBossAS SVN: r103536 - in projects/vfs/trunk/src: test/java/org/jboss/test/vfs and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon Apr 5 12:12:53 EDT 2010
Author: johnbailey
Date: 2010-04-05 12:12:52 -0400 (Mon, 05 Apr 2010)
New Revision: 103536
Added:
projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarFileInputStream.java
projects/vfs/trunk/src/test/java/org/jboss/test/vfs/VirtualJarFileInputStreamTest.java
Modified:
projects/vfs/trunk/src/main/java/org/jboss/vfs/VFSUtils.java
projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarInputStream.java
projects/vfs/trunk/src/test/java/org/jboss/test/vfs/AbstractVFSTest.java
Log:
[JBVFS-155] - A virtual jar file input stream support
Modified: projects/vfs/trunk/src/main/java/org/jboss/vfs/VFSUtils.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/vfs/VFSUtils.java 2010-04-05 13:47:10 UTC (rev 103535)
+++ projects/vfs/trunk/src/main/java/org/jboss/vfs/VFSUtils.java 2010-04-05 16:12:52 UTC (rev 103536)
@@ -43,6 +43,7 @@
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
@@ -760,7 +761,43 @@
return EMPTY_STREAM;
}
+
/**
+ * Get an input stream that will always be consumable as a Zip/Jar file. The input stream will not be an instance
+ * of a JarInputStream, but will stream bytes according to the Zip specification. Using this method, a VFS file
+ * or directory can be written to disk as a normal jar/zip file.
+ *
+ * @param virtualFile The virtual to get a jar file input stream for
+ * @return An input stream returning bytes according to the zip spec
+ * @throws IOException if any problems occur
+ */
+ public static InputStream createJarFileInputStream(final VirtualFile virtualFile) throws IOException {
+ if(virtualFile.isDirectory()) {
+ final VirtualJarInputStream jarInputStream = new VirtualJarInputStream(virtualFile);
+ return new VirtualJarFileInputStream(jarInputStream);
+ }
+ InputStream inputStream = null;
+ try {
+ final byte[] expectedHeader = new byte[4];
+
+ expectedHeader[0] = (byte) (JarEntry.LOCSIG & 0xff);
+ expectedHeader[1] = (byte) ((JarEntry.LOCSIG >>> 8) & 0xff);
+ expectedHeader[2] = (byte) ((JarEntry.LOCSIG >>> 16) & 0xff);
+ expectedHeader[3] = (byte) ((JarEntry.LOCSIG >>> 24) & 0xff);
+
+ inputStream = virtualFile.openStream();
+ final byte[] bytes = new byte[4];
+ final int read = inputStream.read(bytes, 0, 4);
+ if(read < 4 || !Arrays.equals(expectedHeader, bytes)) {
+ throw new IOException("Invalid jar signature " + Arrays.toString(bytes) +" should be " + Arrays.toString(expectedHeader));
+ }
+ } finally {
+ safeClose(inputStream);
+ }
+ return virtualFile.openStream();
+ }
+
+ /**
* Expand a zip file to a destination directory. The directory must exist. If an error occurs, the destination
* directory may contain a partially-extracted archive, so cleanup is up to the caller.
*
Added: projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarFileInputStream.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarFileInputStream.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarFileInputStream.java 2010-04-05 16:12:52 UTC (rev 103536)
@@ -0,0 +1,431 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.vfs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+
+/**
+ * An input stream that can be used to wrap an VirtualJarInputStream (so any VFS dir)
+ * and produce a byte stream following the Zip standard.
+ *
+ * @author <a href="mailto:jbailey at redhat.com">John Bailey</a>
+ */
+public class VirtualJarFileInputStream extends InputStream {
+ // Needs to be sufficiently sized to allow local and central file headers with a single entry name
+ private static final int MINIMUM_BUFFER_LENGTH = 1024;
+
+ private final VirtualJarInputStream virtualJarInputStream;
+
+ private State currentState = State.NOT_STARTED;
+
+ private final List<ProcessedEntry> processedEntries = new LinkedList<ProcessedEntry>();
+ private ProcessedEntry currentEntry;
+
+ private final ByteBuffer buffer;
+ private final CRC32 crc = new CRC32();
+
+ private int currentCentralEntryIdx;
+ private long centralOffset;
+ private long totalRead;
+
+ /**
+ * Create with the minimum put length
+ *
+ * @param virtualJarInputStream The virtual jar input stream to base the stream off of
+ */
+ public VirtualJarFileInputStream(final VirtualJarInputStream virtualJarInputStream) {
+ this(virtualJarInputStream, MINIMUM_BUFFER_LENGTH);
+ }
+
+ /**
+ * Create with the a specified put size
+ *
+ * @param virtualJarInputStream The virtual jar input stream to base the stream off of
+ * @param bufferLength The length of put to use
+ */
+ public VirtualJarFileInputStream(final VirtualJarInputStream virtualJarInputStream, int bufferLength) {
+ if (virtualJarInputStream == null) throw new IllegalArgumentException("virtualJarInputStream is required");
+ if (bufferLength < MINIMUM_BUFFER_LENGTH)
+ throw new IllegalArgumentException("The totalBufferLength must be larger than " + MINIMUM_BUFFER_LENGTH);
+
+ this.virtualJarInputStream = virtualJarInputStream;
+
+ buffer = new ByteBuffer(bufferLength);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read() throws IOException {
+ int readByte = -1;
+ while (currentState != null && (readByte = currentState.read(this)) == -1) {
+ currentState = currentState.getNextState(this);
+ }
+ totalRead++;
+ return readByte;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void close() throws IOException {
+ VFSUtils.safeClose(virtualJarInputStream);
+ super.close();
+ }
+
+ /**
+ * Close the current entry, and calculate the crc value.
+ *
+ * @throws IOException if any problems occur
+ */
+ private void closeCurrent() throws IOException {
+ virtualJarInputStream.closeEntry();
+ currentEntry.crc = crc.getValue();
+ crc.reset();
+ }
+
+ /**
+ * Buffer the content of the local file header for a single entry.
+ *
+ * @return true if the next local file header was buffered
+ * @throws IOException if any problems occur
+ */
+ private boolean bufferLocalFileHeader() throws IOException {
+ buffer.reset();
+ JarEntry jarEntry = virtualJarInputStream.getNextJarEntry();
+
+ if (jarEntry == null)
+ return false;
+
+ currentEntry = new ProcessedEntry(jarEntry, totalRead);
+ processedEntries.add(currentEntry);
+
+
+ bufferInt(ZipEntry.LOCSIG); // Local file header signature
+ bufferShort(10); // Extraction version
+ bufferShort(0); // Flags
+ bufferShort(ZipEntry.STORED); // Compression type
+ bufferInt(jarEntry.getTime()); // Entry time
+ bufferInt(0); // CRC
+ bufferInt(0); // Compressed size
+ bufferInt(0); // Uncompressed size
+ byte[] nameBytes = jarEntry.getName().getBytes("UTF8");
+ bufferShort(nameBytes.length); // Entry name length
+ bufferShort(0); // Extra length
+ buffer(nameBytes);
+ return true;
+ }
+
+ /**
+ * Buffer the central file header record for a single entry.
+ *
+ * @return true if the next central file header was buffered
+ * @throws IOException if any problems occur
+ */
+ private boolean bufferNextCentralFileHeader() throws IOException {
+ buffer.reset();
+
+ if (currentCentralEntryIdx == processedEntries.size())
+ return false;
+
+ ProcessedEntry entry = processedEntries.get(currentCentralEntryIdx++);
+
+ JarEntry jarEntry = entry.jarEntry;
+ bufferInt(ZipEntry.CENSIG); // Central file header signature
+ bufferShort(10); // Version made by
+ bufferShort(10); // Extraction version
+ bufferShort(0); // Flags
+ bufferShort(ZipEntry.STORED); // Compression type
+ bufferInt(jarEntry.getTime()); // Entry time
+ bufferInt(entry.crc); // CRC
+ bufferInt(jarEntry.getSize()); // Compressed size
+ bufferInt(jarEntry.getSize()); // Uncompressed size
+ byte[] nameBytes = jarEntry.getName().getBytes("UTF8");
+ bufferShort(nameBytes.length); // Entry name length
+ bufferShort(0); // Extra field length
+ bufferShort(0); // File comment length
+ bufferShort(0); // Disk number start
+ bufferShort(0); // Internal file attributes
+ bufferInt(0); // External file attributes
+ bufferInt(entry.offset); // Relative offset of local header
+ buffer(nameBytes);
+ return true;
+ }
+
+ /**
+ * Write the central file header records. This is repeated
+ * until all entries have been added to the central file header.
+ *
+ * @throws IOException if any problem occur
+ */
+ private void bufferCentralDirectoryEnd() throws IOException {
+ buffer.reset();
+ long lengthOfCentral = totalRead - centralOffset;
+
+ int count = processedEntries.size();
+ bufferInt(JarEntry.ENDSIG); // End of central directory signature
+ bufferShort(0); // Number of this disk
+ bufferShort(0); // Start of central directory disk
+ bufferShort(count); // Number of processedEntries on disk
+ bufferShort(count); // Total number of processedEntries
+ bufferInt(lengthOfCentral); // Size of central directory
+ bufferInt(centralOffset); // Offset of start of central directory
+ bufferShort(0); // Comment Length
+ }
+
+ /**
+ * Buffer a 32-bit integer in little-endian
+ *
+ * @param i A long representation of a 32 bit int
+ */
+ private void bufferInt(long i) {
+ buffer((byte) (i & 0xff));
+ buffer((byte) ((i >>> 8) & 0xff));
+ buffer((byte) ((i >>> 16) & 0xff));
+ buffer((byte) ((i >>> 24) & 0xff));
+ }
+
+ /**
+ * Buffer a 16-bit short in little-endian
+ *
+ * @param i An int representation of a 16 bit short
+ */
+ private void bufferShort(int i) {
+ buffer((byte) (i & 0xff));
+ buffer((byte) ((i >>> 8) & 0xff));
+ }
+
+ /**
+ * Buffer a single byte
+ *
+ * @param b The byte
+ */
+ private void buffer(byte b) {
+ if(buffer.hasCapacity())
+ buffer.put(b);
+ else
+ throw new IllegalStateException("Buffer does not have enough capacity");
+ }
+
+ /**
+ * Buffer a byte array
+ *
+ * @param bytes The bytes
+ */
+ private void buffer(byte[] bytes) {
+ for (byte b : bytes)
+ buffer(b);
+ }
+
+
+ private class ProcessedEntry {
+ private final JarEntry jarEntry;
+ private final long offset;
+ private long crc;
+
+ private ProcessedEntry(final JarEntry jarEntry, final long offset) {
+ this.jarEntry = jarEntry;
+ this.offset = offset;
+ }
+ }
+
+ /**
+ * Basic state machine that will allow the process to transition between the different process states.
+ *
+ * The following describes the process flow:
+ * [NOT_STARTED] - Initial state
+ * - Does not provide content
+ * - Transitions [LOCAL_ENTRY_HEADER]
+ * [LOCAL_ENTRY_HEADER] - The phase for reading the Local Directory Header
+ * - Provides content of the local directory header by populating and feeding off a buffer
+ * - Transitions to [ENTRY_CONTENT] if the header was written
+ * - Transitions to [START_CENTRAL_DIRECTORY] if this is the last local entry header
+ * [ENTRY_CONTENT] - The phase for reading the content of an entry
+ * - Provides content of the entry using the VirtualJarInputStream
+ * - Transitions to [LOCAL_ENTRY_HEADER]
+ * [START_CENTRAL_DIRECTORY] - Phased used to transition into the central directory
+ * - Does not provide content
+ * - Transitions to [CENTRAL_ENTRY_HEADER]
+ * [CENTRAL_ENTRY_HEADER] - The phase for reading the content of a single central directory header
+ * - Provides content for the central directory header by feeding off a buffer
+ * - Transitions to [CENTRAL_ENTRY_HEADER]
+ * - Transitions to [CENTRAL_END] if there are no more entries
+ * [CENTRAL_END] - The phase for reading the contents of the central directory end
+ * - Provides content for central directory end by feeing off a buffer
+ * - Transitions to NULL to terminate the processing
+ */
+ private enum State {
+ NOT_STARTED {
+ @Override
+ State transition(VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ return LOCAL_ENTRY_HEADER;
+ }
+ },
+ LOCAL_ENTRY_HEADER {
+ boolean buffered;
+ @Override
+ void init(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ buffered = jarFileInputStream.bufferLocalFileHeader();
+ }
+
+ @Override
+ int read(VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ final ByteBuffer buffer = jarFileInputStream.buffer;
+ if (buffered && buffer.hasRemaining())
+ return buffer.get();
+ return -1;
+ }
+
+ @Override
+ State transition(final VirtualJarFileInputStream virtualJarFileInputStream) throws IOException {
+ if (buffered)
+ return ENTRY_CONTENT;
+ return START_CENTRAL_DIRECTORY;
+ }
+ },
+ ENTRY_CONTENT {
+
+ @Override
+ int read(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ final VirtualJarInputStream virtualJarInputStream = jarFileInputStream.virtualJarInputStream;
+ return virtualJarInputStream.read();
+ }
+ @Override
+ State transition(final VirtualJarFileInputStream virtualJarFileInputStream) throws IOException {
+ virtualJarFileInputStream.closeCurrent();
+ return LOCAL_ENTRY_HEADER;
+ }
+ },
+ START_CENTRAL_DIRECTORY {
+ @Override
+ void init(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ jarFileInputStream.centralOffset = jarFileInputStream.totalRead;
+ }
+
+ @Override
+ State transition(final VirtualJarFileInputStream virtualJarFileInputStream) throws IOException {
+ return CENTRAL_ENTRY_HEADER;
+ }
+ },
+ CENTRAL_ENTRY_HEADER {
+ boolean buffered;
+ @Override
+ void init(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ buffered = jarFileInputStream.bufferNextCentralFileHeader();
+ }
+
+ @Override
+ int read(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ final ByteBuffer buffer = jarFileInputStream.buffer;
+ if (buffered && buffer.hasRemaining())
+ return buffer.get();
+ return -1;
+ }
+ @Override
+ State transition(final VirtualJarFileInputStream virtualJarFileInputStream) throws IOException {
+ if (buffered)
+ return CENTRAL_ENTRY_HEADER;
+ return CENTRAL_END;
+ }
+ },
+ CENTRAL_END {
+ @Override
+ void init(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ jarFileInputStream.bufferCentralDirectoryEnd();
+ }
+
+ @Override
+ int read(final VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ final ByteBuffer buffer = jarFileInputStream.buffer;
+ if (buffer.hasRemaining())
+ return buffer.get();
+ return -1;
+ }
+
+ @Override
+ State transition(final VirtualJarFileInputStream virtualJarFileInputStream) throws IOException {
+ return null;
+ }
+ };
+
+
+ void init(VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ }
+
+ abstract State transition(VirtualJarFileInputStream virtualJarFileInputStream) throws IOException;
+
+ int read(VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ return -1;
+ }
+
+ State getNextState(VirtualJarFileInputStream jarFileInputStream) throws IOException {
+ State nextState = transition(jarFileInputStream);
+ if (nextState != null)
+ nextState.init(jarFileInputStream);
+ return nextState;
+ }
+ }
+
+
+ private static class ByteBuffer {
+
+ private final int bufferLength;
+ private final byte[] buffer;
+ private int bufferPosition;
+ private int bufferDepth;
+
+ private ByteBuffer(final int bufferLength) {
+ this.buffer = new byte[bufferLength];
+ this.bufferLength = bufferLength;
+ }
+
+ private boolean hasRemaining() {
+ return bufferPosition < bufferDepth;
+ }
+
+ private boolean hasCapacity() {
+ return bufferDepth < bufferLength;
+ }
+
+ private byte get() {
+ return buffer[bufferPosition++];
+ }
+
+ private void put(byte b) {
+ buffer[bufferDepth++] = b;
+ }
+
+ private void reset() {
+ bufferPosition = 0;
+ bufferDepth = 0;
+ }
+ }
+}
Modified: projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarInputStream.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarInputStream.java 2010-04-05 13:47:10 UTC (rev 103535)
+++ projects/vfs/trunk/src/main/java/org/jboss/vfs/VirtualJarInputStream.java 2010-04-05 16:12:52 UTC (rev 103536)
@@ -267,6 +267,12 @@
return virtualFile.getSize();
}
+ @Override
+ public long getTime()
+ {
+ return virtualFile.getLastModified();
+ }
+
/** {@inheritDoc} **/
@Override
public boolean isDirectory() {
Modified: projects/vfs/trunk/src/test/java/org/jboss/test/vfs/AbstractVFSTest.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/vfs/AbstractVFSTest.java 2010-04-05 13:47:10 UTC (rev 103535)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/vfs/AbstractVFSTest.java 2010-04-05 16:12:52 UTC (rev 103536)
@@ -121,6 +121,10 @@
protected byte[] getContent(VirtualFile virtualFile) throws IOException {
InputStream is = virtualFile.openStream();
+ return getContent(is);
+ }
+
+ protected byte[] getContent(InputStream is) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
VFSUtils.copyStreamAndClose(is, bos);
return bos.toByteArray();
Added: projects/vfs/trunk/src/test/java/org/jboss/test/vfs/VirtualJarFileInputStreamTest.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/vfs/VirtualJarFileInputStreamTest.java (rev 0)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/vfs/VirtualJarFileInputStreamTest.java 2010-04-05 16:12:52 UTC (rev 103536)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.vfs;
+
+import org.jboss.vfs.*;
+import org.jboss.vfs.VirtualJarFileInputStream;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import static org.junit.Assert.assertArrayEquals;
+
+/**
+ * @author <a href="mailto:jbailey at redhat.com">John Bailey</a>
+ */
+public class VirtualJarFileInputStreamTest extends AbstractVFSTest {
+
+ public VirtualJarFileInputStreamTest(final String name) {
+ super(name);
+ }
+
+
+ public void testDirectoryStream() throws Exception {
+ VirtualFile testDir = getVirtualFile("/vfs/test/jar1");
+
+ InputStream inputStream = VFSUtils.createJarFileInputStream(testDir);
+
+ TempDir tempDir = provider.createTempDir("test");
+
+ File tempFile = tempDir.getFile("test.zip");
+
+ VFSUtils.copyStreamAndClose(inputStream, new FileOutputStream(tempFile));
+
+ JarFile jarFile = new JarFile(tempFile);
+
+ assertEntryContent("META-INF/MANIFEST.MF", jarFile, testDir);
+ assertEntry("org/", jarFile);
+ assertEntry("org/jboss/", jarFile);
+ assertEntry("org/jboss/test/", jarFile);
+ assertEntry("org/jboss/test/vfs/", jarFile);
+ assertEntry("org/jboss/test/vfs/support/", jarFile);
+ assertEntry("org/jboss/test/vfs/support/jar1/", jarFile);
+ assertEntryContent("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class", jarFile, testDir);
+ assertEntryContent("org/jboss/test/vfs/support/jar1/ClassInJar1.class", jarFile, testDir);
+ }
+
+ public void testFileStream() throws Exception {
+ VirtualFile testJar = getVirtualFile("/vfs/test/jar1.jar");
+
+ InputStream inputStream = VFSUtils.createJarFileInputStream(testJar);
+
+ TempDir tempDir = provider.createTempDir("test");
+
+ File tempFile = tempDir.getFile("test.zip");
+
+ VFSUtils.copyStreamAndClose(inputStream, new FileOutputStream(tempFile));
+
+ JarFile jarFile = new JarFile(tempFile);
+
+ assertEntry("META-INF/MANIFEST.MF", jarFile);
+ assertEntry("org/", jarFile);
+ assertEntry("org/jboss/", jarFile);
+ assertEntry("org/jboss/test/", jarFile);
+ assertEntry("org/jboss/test/vfs/", jarFile);
+ assertEntry("org/jboss/test/vfs/support/", jarFile);
+ assertEntry("org/jboss/test/vfs/support/jar1/", jarFile);
+ assertEntry("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class", jarFile);
+ assertEntry("org/jboss/test/vfs/support/jar1/ClassInJar1.class", jarFile);
+ }
+
+ public void testInvalidFileStream() throws Exception {
+ VirtualFile testJar = getVirtualFile("/vfs/test/filesonly.mf");
+ try {
+ VFSUtils.createJarFileInputStream(testJar);
+ fail("Should have thrown IOException");
+ } catch (IOException expected) {
+ assertTrue(expected.getMessage().startsWith("Invalid jar signature"));
+ }
+
+ }
+
+ private void assertEntry(String name, JarFile jarFile) throws Exception {
+ JarEntry entry = jarFile.getJarEntry(name);
+ assertNotNull(entry);
+ }
+
+ private void assertEntryContent(String name, JarFile jarFile, VirtualFile parent) throws Exception {
+ JarEntry entry = jarFile.getJarEntry(name);
+ assertNotNull(entry);
+ InputStream entryStream = jarFile.getInputStream(entry);
+ InputStream fileStream = parent.getChild(name).openStream();
+ assertContentEqual(fileStream, entryStream);
+ }
+
+ private void assertContentEqual(InputStream in, InputStream other) throws Exception {
+ assertArrayEquals(getContent(in), getContent(other));
+ }
+}
More information about the jboss-cvs-commits
mailing list