Author: sebb Date: Mon Feb 16 23:13:01 2015 New Revision: 1660245 URL: http://svn.apache.org/r1660245 Log: COMPRESS-306 ArchiveStreamFactory fails to pass on the encoding when creating some streams.
Modified: commons/proper/compress/trunk/src/changes/changes.xml commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveInputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java Modified: commons/proper/compress/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/changes/changes.xml?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/changes/changes.xml (original) +++ commons/proper/compress/trunk/src/changes/changes.xml Mon Feb 16 23:13:01 2015 @@ -54,6 +54,15 @@ breaks backwards compatibility for code This also changes the superclass of ZCompressorInputStream. "> + <action issue="COMPRESS-306" type="fix"> + ArchiveStreamFactory fails to pass on the encoding when creating some streams. + * ArjArchiveInputStream + * CpioArchiveInputStream + * DumpArchiveInputStream + * JarArchiveInputStream + * TarArchiveInputStream + * JarArchiveOutputStream + </action> <action issue="COMPRESS-302" type="fix"> Restore immutability/thread-safety to ArchiveStreamFactory. The class is now immutable provided that the method setEntryEncoding is not used. Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java Mon Feb 16 23:13:01 2015 @@ -150,10 +150,10 @@ public class ArchiveStreamFactory { } /** - * Returns the encoding to use for arj, zip, dump, cpio and tar - * files, or null for the default. + * Returns the encoding to use for arj, jar, zip, dump, cpio and tar + * files, or null for the archiver default. * - * @return entry encoding, or null + * @return entry encoding, or null for the archiver default * @since 1.5 */ public String getEntryEncoding() { @@ -161,9 +161,9 @@ public class ArchiveStreamFactory { } /** - * Sets the encoding to use for arj, zip, dump, cpio and tar files. Use null for the default. + * Sets the encoding to use for arj, jar, zip, dump, cpio and tar files. Use null for the archiver default. * - * @param entryEncoding the entry encoding, null uses the default. + * @param entryEncoding the entry encoding, null uses the archiver default. * @since 1.5 * @deprecated 1.10 use {@link #ArchiveStreamFactory(String)} to specify the encoding * @throws IllegalStateException if the constructor {@link #ArchiveStreamFactory(String)} @@ -227,7 +227,11 @@ public class ArchiveStreamFactory { } } if (JAR.equalsIgnoreCase(archiverName)) { - return new JarArchiveInputStream(in); + if (entryEncoding != null) { + return new JarArchiveInputStream(in, entryEncoding); + } else { + return new JarArchiveInputStream(in); + } } if (CPIO.equalsIgnoreCase(archiverName)) { if (entryEncoding != null) { @@ -254,7 +258,7 @@ public class ArchiveStreamFactory { * Create an archive output stream from an archiver name and an output stream. * * @param archiverName the archive name, - * i.e. {@value #AR}, {@value #ZIP}, {@value #TAR}, {@value #JAR}, {@value #CPIO} or {@value #SEVEN_Z} + * i.e. {@value #AR}, {@value #ZIP}, {@value #TAR}, {@value #JAR} or {@value #CPIO} * @param out the output stream * @return the archive output stream * @throws ArchiveException if the archiver name is not known @@ -290,7 +294,11 @@ public class ArchiveStreamFactory { } } if (JAR.equalsIgnoreCase(archiverName)) { - return new JarArchiveOutputStream(out); + if (entryEncoding != null) { + return new JarArchiveOutputStream(out, entryEncoding); + } else { + return new JarArchiveOutputStream(out); + } } if (CPIO.equalsIgnoreCase(archiverName)) { if (entryEncoding != null) { @@ -339,13 +347,25 @@ public class ArchiveStreamFactory { return new ZipArchiveInputStream(in); } } else if (JarArchiveInputStream.matches(signature, signatureLength)) { - return new JarArchiveInputStream(in); + if (entryEncoding != null) { + return new JarArchiveInputStream(in, entryEncoding); + } else { + return new JarArchiveInputStream(in); + } } else if (ArArchiveInputStream.matches(signature, signatureLength)) { return new ArArchiveInputStream(in); } else if (CpioArchiveInputStream.matches(signature, signatureLength)) { - return new CpioArchiveInputStream(in); + if (entryEncoding != null) { + return new CpioArchiveInputStream(in, entryEncoding); + } else { + return new CpioArchiveInputStream(in); + } } else if (ArjArchiveInputStream.matches(signature, signatureLength)) { - return new ArjArchiveInputStream(in); + if (entryEncoding != null) { + return new ArjArchiveInputStream(in, entryEncoding); + } else { + return new ArjArchiveInputStream(in); + } } else if (SevenZFile.matches(signature, signatureLength)) { throw new StreamingNotSupportedException(SEVEN_Z); } @@ -356,7 +376,7 @@ public class ArchiveStreamFactory { signatureLength = IOUtils.readFully(in, dumpsig); in.reset(); if (DumpArchiveInputStream.matches(dumpsig, signatureLength)) { - return new DumpArchiveInputStream(in); + return new DumpArchiveInputStream(in, entryEncoding); } // Tar needs an even bigger buffer to check the signature; read the first block @@ -365,11 +385,7 @@ public class ArchiveStreamFactory { signatureLength = IOUtils.readFully(in, tarheader); in.reset(); if (TarArchiveInputStream.matches(tarheader, signatureLength)) { - if (entryEncoding != null) { - return new TarArchiveInputStream(in, entryEncoding); - } else { - return new TarArchiveInputStream(in); - } + return new TarArchiveInputStream(in, entryEncoding); } // COMPRESS-117 - improve auto-recognition if (signatureLength >= 512) { @@ -378,7 +394,7 @@ public class ArchiveStreamFactory { tais = new TarArchiveInputStream(new ByteArrayInputStream(tarheader)); // COMPRESS-191 - verify the header checksum if (tais.getNextTarEntry().isCheckSumOK()) { - return new TarArchiveInputStream(in); + return new TarArchiveInputStream(in, encoding); } } catch (Exception e) { // NOPMD // can generate IllegalArgumentException as well Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java Mon Feb 16 23:13:01 2015 @@ -91,7 +91,10 @@ public class CpioArchiveInputStream exte /** * The encoding to use for filenames and labels. */ - private final ZipEncoding encoding; + private final ZipEncoding zipEncoding; + + // the provided encoding (for unit tests) + final String encoding; /** * Construct the cpio input stream with a blocksize of {@link @@ -150,7 +153,8 @@ public class CpioArchiveInputStream exte public CpioArchiveInputStream(final InputStream in, int blockSize, String encoding) { this.in = in; this.blockSize = blockSize; - this.encoding = ZipEncodingHelper.getZipEncoding(encoding); + this.encoding = encoding; + this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); } /** @@ -444,7 +448,7 @@ public class CpioArchiveInputStream exte byte tmpBuffer[] = new byte[length - 1]; readFully(tmpBuffer, 0, tmpBuffer.length); this.in.read(); - return encoding.decode(tmpBuffer); + return zipEncoding.decode(tmpBuffer); } /** Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java Mon Feb 16 23:13:01 2015 @@ -92,7 +92,10 @@ public class CpioArchiveOutputStream ext /** * The encoding to use for filenames and labels. */ - private final ZipEncoding encoding; + private final ZipEncoding zipEncoding; + + // the provided encoding (for unit tests) + final String encoding; /** * Construct the cpio output stream with a specified format, a @@ -157,7 +160,8 @@ public class CpioArchiveOutputStream ext } this.entryFormat = format; this.blockSize = blockSize; - this.encoding = ZipEncodingHelper.getZipEncoding(encoding); + this.encoding = encoding; + this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); } /** @@ -534,7 +538,7 @@ public class CpioArchiveOutputStream ext * @throws IOException if the string couldn't be written */ private void writeCString(final String str) throws IOException { - ByteBuffer buf = encoding.encode(str); + ByteBuffer buf = zipEncoding.encode(str); final int len = buf.limit() - buf.position(); out.write(buf.array(), buf.arrayOffset(), len); out.write('\0'); Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/dump/DumpArchiveInputStream.java Mon Feb 16 23:13:01 2015 @@ -74,7 +74,10 @@ public class DumpArchiveInputStream exte /** * The encoding to use for filenames and labels. */ - private final ZipEncoding encoding; + private final ZipEncoding zipEncoding; + + // the provided encoding (for unit tests) + final String encoding; /** * Constructor using the platform's default encoding for file @@ -99,7 +102,8 @@ public class DumpArchiveInputStream exte throws ArchiveException { this.raw = new TapeInputStream(is); this.hasHitEOF = false; - this.encoding = ZipEncodingHelper.getZipEncoding(encoding); + this.encoding = encoding; + this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); try { // read header, verify it's a dump archive. @@ -110,7 +114,7 @@ public class DumpArchiveInputStream exte } // get summary information - summary = new DumpArchiveSummary(headerBytes, this.encoding); + summary = new DumpArchiveSummary(headerBytes, this.zipEncoding); // reset buffer with actual block size. raw.resetBlockSize(summary.getNTRec(), summary.isCompressed()); @@ -351,7 +355,7 @@ public class DumpArchiveInputStream exte byte type = blockBuffer[i + 6]; - String name = DumpArchiveUtil.decode(encoding, blockBuffer, i + 8, blockBuffer[i + 7]); + String name = DumpArchiveUtil.decode(zipEncoding, blockBuffer, i + 8, blockBuffer[i + 7]); if (".".equals(name) || "..".equals(name)) { // do nothing... Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveInputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveInputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveInputStream.java Mon Feb 16 23:13:01 2015 @@ -32,10 +32,26 @@ import org.apache.commons.compress.archi */ public class JarArchiveInputStream extends ZipArchiveInputStream { + /** + * Creates an instance from the input stream using the default encoding. + * + * @param inputStream the input stream to wrap + */ public JarArchiveInputStream( final InputStream inputStream ) { super(inputStream); } + /** + * Creates an instance from the input stream using the specified encoding. + * + * @param inputStream the input stream to wrap + * @param encoding the encoding to use + * @since 1.10 + */ + public JarArchiveInputStream( final InputStream inputStream, final String encoding ) { + super(inputStream, encoding); + } + public JarArchiveEntry getNextJarEntry() throws IOException { ZipArchiveEntry entry = getNextZipEntry(); return entry == null ? null : new JarArchiveEntry(entry); Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/jar/JarArchiveOutputStream.java Mon Feb 16 23:13:01 2015 @@ -41,6 +41,18 @@ public class JarArchiveOutputStream exte super(out); } + /** + * Create and instance that wraps the output stream using the provided encoding. + * + * @param out the output stream to wrap + * @param encoding the encoding to use. Use null for the platform default. + * @since 1.10 + */ + public JarArchiveOutputStream(final OutputStream out, final String encoding) { + super(out); + setEncoding(encoding); + } + // @throws ClassCastException if entry is not an instance of ZipArchiveEntry @Override public void putArchiveEntry(ArchiveEntry ze) throws IOException { Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java Mon Feb 16 23:13:01 2015 @@ -73,7 +73,10 @@ public class TarArchiveInputStream exten private TarArchiveEntry currEntry; /** The encoding of the file */ - private final ZipEncoding encoding; + private final ZipEncoding zipEncoding; + + // the provided encoding (for unit tests) + final String encoding; /** * Constructor for TarInputStream. @@ -137,7 +140,8 @@ public class TarArchiveInputStream exten String encoding) { this.is = is; this.hasHitEOF = false; - this.encoding = ZipEncodingHelper.getZipEncoding(encoding); + this.encoding = encoding; + this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); this.recordSize = recordSize; this.blockSize = blockSize; } @@ -271,7 +275,7 @@ public class TarArchiveInputStream exten } try { - currEntry = new TarArchiveEntry(headerBuf, encoding); + currEntry = new TarArchiveEntry(headerBuf, zipEncoding); } catch (IllegalArgumentException e) { IOException ioe = new IOException("Error detected parsing the header"); ioe.initCause(e); @@ -289,7 +293,7 @@ public class TarArchiveInputStream exten // entry return null; } - currEntry.setLinkName(encoding.decode(longLinkData)); + currEntry.setLinkName(zipEncoding.decode(longLinkData)); } if (currEntry.isGNULongNameEntry()) { @@ -300,7 +304,7 @@ public class TarArchiveInputStream exten // entry return null; } - currEntry.setName(encoding.decode(longNameData)); + currEntry.setName(zipEncoding.decode(longNameData)); } if (currEntry.isPaxHeader()){ // Process Pax headers Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java Mon Feb 16 23:13:01 2015 @@ -84,7 +84,10 @@ public class TarArchiveOutputStream exte private final OutputStream out; - private final ZipEncoding encoding; + private final ZipEncoding zipEncoding; + + // the provided encoding (for unit tests) + final String encoding; private boolean addPaxHeadersForNonAsciiNames = false; private static final ZipEncoding ASCII = @@ -150,7 +153,8 @@ public class TarArchiveOutputStream exte public TarArchiveOutputStream(OutputStream os, int blockSize, int recordSize, String encoding) { out = new CountingOutputStream(os); - this.encoding = ZipEncodingHelper.getZipEncoding(encoding); + this.encoding = encoding; + this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); this.assemLen = 0; this.assemBuf = new byte[recordSize]; @@ -301,7 +305,7 @@ public class TarArchiveOutputStream exte writePaxHeaders(entry, entryName, paxHeaders); } - entry.writeEntryHeader(recordBuf, encoding, + entry.writeEntryHeader(recordBuf, zipEncoding, bigNumberMode == BIGNUMBER_STAR); writeRecord(recordBuf); @@ -660,7 +664,7 @@ public class TarArchiveOutputStream exte Map<String, String> paxHeaders, String paxHeaderName, byte linkType, String fieldName) throws IOException { - final ByteBuffer encodedName = encoding.encode(name); + final ByteBuffer encodedName = zipEncoding.encode(name); final int len = encodedName.limit() - encodedName.position(); if (len >= TarConstants.NAMELEN) { Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java Mon Feb 16 23:13:01 2015 @@ -61,6 +61,9 @@ public class ZipArchiveInputStream exten /** The zip encoding to use for filenames and the file comment. */ private final ZipEncoding zipEncoding; + // the provided encoding (for unit tests) + final String encoding; + /** Whether to look for and use Unicode extra fields. */ private final boolean useUnicodeExtraFields; @@ -139,6 +142,10 @@ public class ZipArchiveInputStream exten private int entriesRead = 0; + /** + * Create an instance using UTF-8 encoding + * @param inputStream the stream to wrap + */ public ZipArchiveInputStream(InputStream inputStream) { this(inputStream, ZipEncodingHelper.UTF8); } @@ -175,6 +182,7 @@ public class ZipArchiveInputStream exten String encoding, boolean useUnicodeExtraFields, boolean allowStoredEntriesWithDataDescriptor) { + this.encoding = encoding; zipEncoding = ZipEncodingHelper.getZipEncoding(encoding); this.useUnicodeExtraFields = useUnicodeExtraFields; in = new PushbackInputStream(inputStream, buf.capacity()); Modified: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java?rev=1660245&r1=1660244&r2=1660245&view=diff ============================================================================== --- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java (original) +++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java Mon Feb 16 23:13:01 2015 @@ -18,7 +18,9 @@ */ package org.apache.commons.compress.archivers; +import static org.apache.commons.compress.AbstractTestCase.getFile; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -26,8 +28,15 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; +import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream; +import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream; +import org.apache.commons.compress.archivers.dump.DumpArchiveInputStream; +import org.apache.commons.compress.archivers.jar.JarArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.junit.Test; @@ -147,4 +156,249 @@ public class ArchiveStreamFactoryTest { fis.close(); } } + + @Test + public void testEncodingCtor() { + ArchiveStreamFactory fac = new ArchiveStreamFactory(); + assertNull(fac.getEntryEncoding()); + fac = new ArchiveStreamFactory(null); + assertNull(fac.getEntryEncoding()); + fac = new ArchiveStreamFactory("UTF-8"); + assertEquals("UTF-8", fac.getEntryEncoding()); + } + + @Test + @SuppressWarnings("deprecation") + public void testEncodingDeprecated() { + ArchiveStreamFactory fac = new ArchiveStreamFactory(); + assertNull(fac.getEntryEncoding()); + fac.setEntryEncoding("UTF-8"); + assertEquals("UTF-8", fac.getEntryEncoding()); + fac.setEntryEncoding("US_ASCII"); + assertEquals("US_ASCII", fac.getEntryEncoding()); + fac = new ArchiveStreamFactory("UTF-8"); + assertEquals("UTF-8", fac.getEntryEncoding()); + try { + fac.setEntryEncoding("US_ASCII"); + fail("Expected IllegalStateException"); + } catch (IllegalStateException ise) { + // expected + } + } + + static class TestData { + final String testFile; + final String expectedEncoding; + final ArchiveStreamFactory fac; + final String fieldName; + final String type; + final boolean hasOutputStream; + TestData(String testFile, String type, boolean hasOut, String expectedEncoding, ArchiveStreamFactory fac, String fieldName) { + this.testFile = testFile; + this.expectedEncoding = expectedEncoding; + this.fac = fac; + this.fieldName = fieldName; + this.type = type; + this.hasOutputStream = hasOut; + } + } + + @SuppressWarnings("deprecation") // test of deprecated method + static ArchiveStreamFactory getFactory(String entryEncoding) { + ArchiveStreamFactory fac = new ArchiveStreamFactory(); + fac.setEntryEncoding(entryEncoding); + return fac; + } + // The different factory types + private static final ArchiveStreamFactory FACTORY = new ArchiveStreamFactory(); + private static final ArchiveStreamFactory FACTORY_UTF8 = new ArchiveStreamFactory("UTF-8"); + private static final ArchiveStreamFactory FACTORY_ASCII = new ArchiveStreamFactory("ASCII"); + private static final ArchiveStreamFactory FACTORY_SET_UTF8 = getFactory("UTF-8"); + private static final ArchiveStreamFactory FACTORY_SET_ASCII = getFactory("ASCII"); + + // Default encoding if none is provided (not even null) + // The test currently assumes that the output default is the same as the input default + private static final String ARJ_DEFAULT; + private static final String DUMP_DEFAULT; + + private static final String ZIP_DEFAULT = getField(new ZipArchiveInputStream(null),"encoding"); + private static final String CPIO_DEFAULT = getField(new CpioArchiveInputStream(null),"encoding"); + private static final String TAR_DEFAULT = getField(new TarArchiveInputStream(null),"encoding"); + private static final String JAR_DEFAULT = getField(new JarArchiveInputStream(null),"encoding"); + + static { + String dflt; + dflt = "??"; + try { + dflt = getField(new ArjArchiveInputStream(new FileInputStream(getFile("bla.arj"))), "charsetName"); + } catch (ArchiveException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + ARJ_DEFAULT = dflt; + dflt = "??"; + try { + dflt = getField(new DumpArchiveInputStream(new FileInputStream(getFile("bla.dump"))), "encoding"); + } catch (ArchiveException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + DUMP_DEFAULT = dflt; + } + + static final TestData[] TESTS = { + new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, ARJ_DEFAULT, FACTORY, "charsetName"), + new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "UTF-8", FACTORY_UTF8, "charsetName"), + new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "ASCII", FACTORY_ASCII, "charsetName"), + new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "UTF-8", FACTORY_SET_UTF8, "charsetName"), + new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "ASCII", FACTORY_SET_ASCII, "charsetName"), + + new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, CPIO_DEFAULT, FACTORY, "encoding"), + new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "UTF-8", FACTORY_UTF8, "encoding"), + new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "ASCII", FACTORY_ASCII, "encoding"), + new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "UTF-8", FACTORY_SET_UTF8, "encoding"), + new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "ASCII", FACTORY_SET_ASCII, "encoding"), + + new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, DUMP_DEFAULT, FACTORY, "encoding"), + new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "UTF-8", FACTORY_UTF8, "encoding"), + new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "ASCII", FACTORY_ASCII, "encoding"), + new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "UTF-8", FACTORY_SET_UTF8, "encoding"), + new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "ASCII", FACTORY_SET_ASCII, "encoding"), + + new TestData("bla.tar", ArchiveStreamFactory.TAR, true, TAR_DEFAULT, FACTORY, "encoding"), + new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "UTF-8", FACTORY_UTF8, "encoding"), + new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "ASCII", FACTORY_ASCII, "encoding"), + new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "UTF-8", FACTORY_SET_UTF8, "encoding"), + new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "ASCII", FACTORY_SET_ASCII, "encoding"), + + new TestData("bla.jar", ArchiveStreamFactory.JAR, true, JAR_DEFAULT, FACTORY, "encoding"), + new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "UTF-8", FACTORY_UTF8, "encoding"), + new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "ASCII", FACTORY_ASCII, "encoding"), + new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "UTF-8", FACTORY_SET_UTF8, "encoding"), + new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "ASCII", FACTORY_SET_ASCII, "encoding"), + + new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, ZIP_DEFAULT, FACTORY, "encoding"), + new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "UTF-8", FACTORY_UTF8, "encoding"), + new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "ASCII", FACTORY_ASCII, "encoding"), + new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "UTF-8", FACTORY_SET_UTF8, "encoding"), + new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "ASCII", FACTORY_SET_ASCII, "encoding"), + }; + + @Test + public void testEncodingInputStreamAutodetect() throws Exception { + int failed = 0; + for(int i = 1; i <= TESTS.length; i++) { + TestData test = TESTS[i-1]; + ArchiveInputStream ais = getInputStreamFor(test.testFile, test.fac); + final String field = getField(ais,test.fieldName); + if (!eq(test.expectedEncoding,field)) { + System.out.println("Failed test " + i + ". expected: " + test.expectedEncoding + " actual: " + field + " type: " + test.type); + failed++; + } + } + if (failed > 0) { + fail("Tests failed: " + failed); + } + } + + @Test + public void testEncodingInputStream() throws Exception { + int failed = 0; + for(int i = 1; i <= TESTS.length; i++) { + TestData test = TESTS[i-1]; + ArchiveInputStream ais = getInputStreamFor(test.type, test.testFile, test.fac); + final String field = getField(ais,test.fieldName); + if (!eq(test.expectedEncoding,field)) { + System.out.println("Failed test " + i + ". expected: " + test.expectedEncoding + " actual: " + field + " type: " + test.type); + failed++; + } + } + if (failed > 0) { + fail("Tests failed: " + failed); + } + } + + @Test + public void testEncodingOutputStream() throws Exception { + int failed = 0; + for(int i = 1; i <= TESTS.length; i++) { + TestData test = TESTS[i-1]; + if (test.hasOutputStream) { + ArchiveOutputStream ais = getOutputStreamFor(test.type, test.fac); + final String field = getField(ais, test.fieldName); + if (!eq(test.expectedEncoding, field)) { + System.out.println("Failed test " + i + ". expected: " + test.expectedEncoding + " actual: " + field + " type: " + test.type); + failed++; + } + } + } + if (failed > 0) { + fail("Tests failed: " + failed); + } + } + + // equals allowing null + private static boolean eq(String exp, String act) { + if (exp == null) { + return act == null; + } + return exp.equals(act); + } + + private static String getField(Object instance, String name) { + Class<?> cls = instance.getClass(); + Field fld; + try { + fld = cls.getDeclaredField(name); + } catch (NoSuchFieldException nsfe) { + try { + fld = cls.getSuperclass().getDeclaredField(name); + } catch (NoSuchFieldException e) { + System.out.println("Cannot find " + name + " in class " + instance.getClass().getSimpleName()); + return "??"; + } + } + boolean isAccessible = fld.isAccessible(); + try { + if (!isAccessible) { + fld.setAccessible(true); + } + final Object object = fld.get(instance); + if (object instanceof String || object == null) { + return (String) object; + } else { + System.out.println("Wrong type: " + object.getClass().getCanonicalName() + " for " + name + " in class " + instance.getClass().getSimpleName()); + return "??"; + } + } catch (Exception e) { + e.printStackTrace(); + return "??"; + } finally { + if (!isAccessible) { + fld.setAccessible(isAccessible); + } + } + } + + private ArchiveInputStream getInputStreamFor(String resource, ArchiveStreamFactory factory) + throws IOException, ArchiveException { + return factory.createArchiveInputStream( + new BufferedInputStream(new FileInputStream( + getFile(resource)))); + } + + private ArchiveInputStream getInputStreamFor(String type, String resource, ArchiveStreamFactory factory) + throws IOException, ArchiveException { + return factory.createArchiveInputStream( + type, + new BufferedInputStream(new FileInputStream( + getFile(resource)))); + } + + private ArchiveOutputStream getOutputStreamFor(String type, ArchiveStreamFactory factory) + throws IOException, ArchiveException { + return factory.createArchiveOutputStream(type, new ByteArrayOutputStream()); + } }