ArchiveStreamFactory.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  * http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing,
  13.  * software distributed under the License is distributed on an
  14.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15.  * KIND, either express or implied.  See the License for the
  16.  * specific language governing permissions and limitations
  17.  * under the License.
  18.  */
  19. package org.apache.commons.compress.archivers;

  20. import java.io.ByteArrayInputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.OutputStream;
  24. import java.security.AccessController;
  25. import java.security.PrivilegedAction;
  26. import java.util.Collections;
  27. import java.util.Locale;
  28. import java.util.ServiceLoader;
  29. import java.util.Set;
  30. import java.util.SortedMap;
  31. import java.util.TreeMap;

  32. import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
  33. import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream;
  34. import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream;
  35. import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
  36. import org.apache.commons.compress.archivers.cpio.CpioArchiveOutputStream;
  37. import org.apache.commons.compress.archivers.dump.DumpArchiveInputStream;
  38. import org.apache.commons.compress.archivers.jar.JarArchiveInputStream;
  39. import org.apache.commons.compress.archivers.jar.JarArchiveOutputStream;
  40. import org.apache.commons.compress.archivers.sevenz.SevenZFile;
  41. import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
  42. import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
  43. import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
  44. import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
  45. import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
  46. import org.apache.commons.compress.utils.IOUtils;
  47. import org.apache.commons.compress.utils.Sets;

  48. /**
  49.  * Factory to create Archive[In|Out]putStreams from names or the first bytes of the InputStream. In order to add other implementations, you should extend
  50.  * ArchiveStreamFactory and override the appropriate methods (and call their implementation from super of course).
  51.  *
  52.  * Compressing a ZIP-File:
  53.  *
  54.  * <pre>
  55.  * final OutputStream out = Files.newOutputStream(output.toPath());
  56.  * ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, out);
  57.  *
  58.  * os.putArchiveEntry(new ZipArchiveEntry("testdata/test1.xml"));
  59.  * IOUtils.copy(Files.newInputStream(file1.toPath()), os);
  60.  * os.closeArchiveEntry();
  61.  *
  62.  * os.putArchiveEntry(new ZipArchiveEntry("testdata/test2.xml"));
  63.  * IOUtils.copy(Files.newInputStream(file2.toPath()), os);
  64.  * os.closeArchiveEntry();
  65.  * os.close();
  66.  * </pre>
  67.  *
  68.  * Decompressing a ZIP-File:
  69.  *
  70.  * <pre>
  71.  * final InputStream is = Files.newInputStream(input.toPath());
  72.  * ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, is);
  73.  * ZipArchiveEntry entry = (ZipArchiveEntry) in.getNextEntry();
  74.  * OutputStream out = Files.newOutputStream(dir.toPath().resolve(entry.getName()));
  75.  * IOUtils.copy(in, out);
  76.  * out.close();
  77.  * in.close();
  78.  * </pre>
  79.  *
  80.  * @Immutable provided that the deprecated method setEntryEncoding is not used.
  81.  * @ThreadSafe even if the deprecated method setEntryEncoding is used
  82.  */
  83. public class ArchiveStreamFactory implements ArchiveStreamProvider {

  84.     private static final int TAR_HEADER_SIZE = 512;

  85.     private static final int TAR_TEST_ENTRY_COUNT = 10;

  86.     private static final int DUMP_SIGNATURE_SIZE = 32;

  87.     private static final int SIGNATURE_SIZE = 12;

  88.     /**
  89.      * The singleton instance using the platform default encoding.
  90.      *
  91.      * @since 1.21
  92.      */
  93.     public static final ArchiveStreamFactory DEFAULT = new ArchiveStreamFactory();

  94.     /**
  95.      * Constant (value {@value}) used to identify the APK archive format.
  96.      * <p>
  97.      * APK file extensions are .apk, .xapk, .apks, .apkm
  98.      * </p>
  99.      *
  100.      * @since 1.22
  101.      */
  102.     public static final String APK = "apk";

  103.     /**
  104.      * Constant (value {@value}) used to identify the XAPK archive format.
  105.      * <p>
  106.      * APK file extensions are .apk, .xapk, .apks, .apkm
  107.      * </p>
  108.      *
  109.      * @since 1.22
  110.      */
  111.     public static final String XAPK = "xapk";

  112.     /**
  113.      * Constant (value {@value}) used to identify the APKS archive format.
  114.      * <p>
  115.      * APK file extensions are .apk, .xapk, .apks, .apkm
  116.      * </p>
  117.      *
  118.      * @since 1.22
  119.      */
  120.     public static final String APKS = "apks";

  121.     /**
  122.      * Constant (value {@value}) used to identify the APKM archive format.
  123.      * <p>
  124.      * APK file extensions are .apk, .xapk, .apks, .apkm
  125.      * </p>
  126.      *
  127.      * @since 1.22
  128.      */
  129.     public static final String APKM = "apkm";

  130.     /**
  131.      * Constant (value {@value}) used to identify the AR archive format.
  132.      *
  133.      * @since 1.1
  134.      */
  135.     public static final String AR = "ar";

  136.     /**
  137.      * Constant (value {@value}) used to identify the ARJ archive format. Not supported as an output stream type.
  138.      *
  139.      * @since 1.6
  140.      */
  141.     public static final String ARJ = "arj";

  142.     /**
  143.      * Constant (value {@value}) used to identify the CPIO archive format.
  144.      *
  145.      * @since 1.1
  146.      */
  147.     public static final String CPIO = "cpio";

  148.     /**
  149.      * Constant (value {@value}) used to identify the UNIX DUMP archive format. Not supported as an output stream type.
  150.      *
  151.      * @since 1.3
  152.      */
  153.     public static final String DUMP = "dump";

  154.     /**
  155.      * Constant (value {@value}) used to identify the JAR archive format.
  156.      *
  157.      * @since 1.1
  158.      */
  159.     public static final String JAR = "jar";

  160.     /**
  161.      * Constant used to identify the TAR archive format.
  162.      *
  163.      * @since 1.1
  164.      */
  165.     public static final String TAR = "tar";

  166.     /**
  167.      * Constant (value {@value}) used to identify the ZIP archive format.
  168.      *
  169.      * @since 1.1
  170.      */
  171.     public static final String ZIP = "zip";

  172.     /**
  173.      * Constant (value {@value}) used to identify the 7z archive format.
  174.      *
  175.      * @since 1.8
  176.      */
  177.     public static final String SEVEN_Z = "7z";

  178.     private static Iterable<ArchiveStreamProvider> archiveStreamProviderIterable() {
  179.         return ServiceLoader.load(ArchiveStreamProvider.class, ClassLoader.getSystemClassLoader());
  180.     }

  181.     /**
  182.      * Try to determine the type of Archiver
  183.      *
  184.      * @param in input stream
  185.      * @return type of archiver if found
  186.      * @throws ArchiveException if an archiver cannot be detected in the stream
  187.      * @since 1.14
  188.      */
  189.     public static String detect(final InputStream in) throws ArchiveException {
  190.         if (in == null) {
  191.             throw new IllegalArgumentException("Stream must not be null.");
  192.         }

  193.         if (!in.markSupported()) {
  194.             throw new IllegalArgumentException("Mark is not supported.");
  195.         }

  196.         final byte[] signature = new byte[SIGNATURE_SIZE];
  197.         in.mark(signature.length);
  198.         int signatureLength = -1;
  199.         try {
  200.             signatureLength = IOUtils.readFully(in, signature);
  201.             in.reset();
  202.         } catch (final IOException e) {
  203.             throw new ArchiveException("IOException while reading signature.", e);
  204.         }

  205.         // For now JAR files are detected as ZIP files.
  206.         if (ZipArchiveInputStream.matches(signature, signatureLength)) {
  207.             return ZIP;
  208.         }
  209.         // For now JAR files are detected as ZIP files.
  210.         if (JarArchiveInputStream.matches(signature, signatureLength)) {
  211.             return JAR;
  212.         }
  213.         if (ArArchiveInputStream.matches(signature, signatureLength)) {
  214.             return AR;
  215.         }
  216.         if (CpioArchiveInputStream.matches(signature, signatureLength)) {
  217.             return CPIO;
  218.         }
  219.         if (ArjArchiveInputStream.matches(signature, signatureLength)) {
  220.             return ARJ;
  221.         }
  222.         if (SevenZFile.matches(signature, signatureLength)) {
  223.             return SEVEN_Z;
  224.         }

  225.         // Dump needs a bigger buffer to check the signature;
  226.         final byte[] dumpsig = new byte[DUMP_SIGNATURE_SIZE];
  227.         in.mark(dumpsig.length);
  228.         try {
  229.             signatureLength = IOUtils.readFully(in, dumpsig);
  230.             in.reset();
  231.         } catch (final IOException e) {
  232.             throw new ArchiveException("IOException while reading dump signature", e);
  233.         }
  234.         if (DumpArchiveInputStream.matches(dumpsig, signatureLength)) {
  235.             return DUMP;
  236.         }

  237.         // Tar needs an even bigger buffer to check the signature; read the first block
  238.         final byte[] tarHeader = new byte[TAR_HEADER_SIZE];
  239.         in.mark(tarHeader.length);
  240.         try {
  241.             signatureLength = IOUtils.readFully(in, tarHeader);
  242.             in.reset();
  243.         } catch (final IOException e) {
  244.             throw new ArchiveException("IOException while reading tar signature", e);
  245.         }
  246.         if (TarArchiveInputStream.matches(tarHeader, signatureLength)) {
  247.             return TAR;
  248.         }

  249.         // COMPRESS-117
  250.         if (signatureLength >= TAR_HEADER_SIZE) {
  251.             try (TarArchiveInputStream inputStream = new TarArchiveInputStream(new ByteArrayInputStream(tarHeader))) {
  252.                 // COMPRESS-191 - verify the header checksum
  253.                 // COMPRESS-644 - do not allow zero byte file entries
  254.                 TarArchiveEntry entry = inputStream.getNextEntry();
  255.                 // try to find the first non-directory entry within the first 10 entries.
  256.                 int count = 0;
  257.                 while (entry != null && entry.isDirectory() && entry.isCheckSumOK() && count++ < TAR_TEST_ENTRY_COUNT) {
  258.                     entry = inputStream.getNextEntry();
  259.                 }
  260.                 if (entry != null && entry.isCheckSumOK() && !entry.isDirectory() && entry.getSize() > 0 || count > 0) {
  261.                     return TAR;
  262.                 }
  263.             } catch (final Exception ignored) {
  264.                 // can generate IllegalArgumentException as well as IOException auto-detection, simply not a TAR ignored
  265.             }
  266.         }
  267.         throw new ArchiveException("No Archiver found for the stream signature");
  268.     }

  269.     /**
  270.      * Constructs a new sorted map from input stream provider names to provider objects.
  271.      *
  272.      * <p>
  273.      * The map returned by this method will have one entry for each provider for which support is available in the current Java virtual machine. If two or more
  274.      * supported provider have the same name then the resulting map will contain just one of them; which one it will contain is not specified.
  275.      * </p>
  276.      *
  277.      * <p>
  278.      * The invocation of this method, and the subsequent use of the resulting map, may cause time-consuming disk or network I/O operations to occur. This method
  279.      * is provided for applications that need to enumerate all of the available providers, for example to allow user provider selection.
  280.      * </p>
  281.      *
  282.      * <p>
  283.      * This method may return different results at different times if new providers are dynamically made available to the current Java virtual machine.
  284.      * </p>
  285.      *
  286.      * @return An immutable, map from names to provider objects
  287.      * @since 1.13
  288.      */
  289.     public static SortedMap<String, ArchiveStreamProvider> findAvailableArchiveInputStreamProviders() {
  290.         return AccessController.doPrivileged((PrivilegedAction<SortedMap<String, ArchiveStreamProvider>>) () -> {
  291.             final TreeMap<String, ArchiveStreamProvider> map = new TreeMap<>();
  292.             putAll(DEFAULT.getInputStreamArchiveNames(), DEFAULT, map);
  293.             archiveStreamProviderIterable().forEach(provider -> putAll(provider.getInputStreamArchiveNames(), provider, map));
  294.             return map;
  295.         });
  296.     }

  297.     /**
  298.      * Constructs a new sorted map from output stream provider names to provider objects.
  299.      *
  300.      * <p>
  301.      * The map returned by this method will have one entry for each provider for which support is available in the current Java virtual machine. If two or more
  302.      * supported provider have the same name then the resulting map will contain just one of them; which one it will contain is not specified.
  303.      * </p>
  304.      *
  305.      * <p>
  306.      * The invocation of this method, and the subsequent use of the resulting map, may cause time-consuming disk or network I/O operations to occur. This method
  307.      * is provided for applications that need to enumerate all of the available providers, for example to allow user provider selection.
  308.      * </p>
  309.      *
  310.      * <p>
  311.      * This method may return different results at different times if new providers are dynamically made available to the current Java virtual machine.
  312.      * </p>
  313.      *
  314.      * @return An immutable, map from names to provider objects
  315.      * @since 1.13
  316.      */
  317.     public static SortedMap<String, ArchiveStreamProvider> findAvailableArchiveOutputStreamProviders() {
  318.         return AccessController.doPrivileged((PrivilegedAction<SortedMap<String, ArchiveStreamProvider>>) () -> {
  319.             final TreeMap<String, ArchiveStreamProvider> map = new TreeMap<>();
  320.             putAll(DEFAULT.getOutputStreamArchiveNames(), DEFAULT, map);
  321.             archiveStreamProviderIterable().forEach(provider -> putAll(provider.getOutputStreamArchiveNames(), provider, map));
  322.             return map;
  323.         });
  324.     }

  325.     static void putAll(final Set<String> names, final ArchiveStreamProvider provider, final TreeMap<String, ArchiveStreamProvider> map) {
  326.         names.forEach(name -> map.put(toKey(name), provider));
  327.     }

  328.     private static String toKey(final String name) {
  329.         return name.toUpperCase(Locale.ROOT);
  330.     }

  331.     /**
  332.      * Entry encoding, null for the default.
  333.      */
  334.     private volatile String entryEncoding;

  335.     private SortedMap<String, ArchiveStreamProvider> archiveInputStreamProviders;

  336.     private SortedMap<String, ArchiveStreamProvider> archiveOutputStreamProviders;

  337.     /**
  338.      * Constructs an instance using the platform default encoding.
  339.      */
  340.     public ArchiveStreamFactory() {
  341.         this(null);
  342.     }

  343.     /**
  344.      * Constructs an instance using the specified encoding.
  345.      *
  346.      * @param entryEncoding the encoding to be used.
  347.      *
  348.      * @since 1.10
  349.      */
  350.     public ArchiveStreamFactory(final String entryEncoding) {
  351.         this.entryEncoding = entryEncoding;
  352.     }

  353.     /**
  354.      * Creates an archive input stream from an input stream, autodetecting the archive type from the first few bytes of the stream. The InputStream must support
  355.      * marks, like BufferedInputStream.
  356.      *
  357.      * @param <I> The {@link ArchiveInputStream} type.
  358.      * @param in  the input stream
  359.      * @return the archive input stream
  360.      * @throws ArchiveException               if the archiver name is not known
  361.      * @throws StreamingNotSupportedException if the format cannot be read from a stream
  362.      * @throws IllegalArgumentException       if the stream is null or does not support mark
  363.      */
  364.     public <I extends ArchiveInputStream<? extends ArchiveEntry>> I createArchiveInputStream(final InputStream in) throws ArchiveException {
  365.         return createArchiveInputStream(detect(in), in);
  366.     }

  367.     /**
  368.      * Creates an archive input stream from an archiver name and an input stream.
  369.      *
  370.      * @param <I>          The {@link ArchiveInputStream} type.
  371.      * @param archiverName the archive name, i.e. {@value #AR}, {@value #ARJ}, {@value #ZIP}, {@value #TAR}, {@value #JAR}, {@value #CPIO}, {@value #DUMP} or
  372.      *                     {@value #SEVEN_Z}
  373.      * @param in           the input stream
  374.      * @return the archive input stream
  375.      * @throws ArchiveException               if the archiver name is not known
  376.      * @throws StreamingNotSupportedException if the format cannot be read from a stream
  377.      * @throws IllegalArgumentException       if the archiver name or stream is null
  378.      */
  379.     public <I extends ArchiveInputStream<? extends ArchiveEntry>> I createArchiveInputStream(final String archiverName, final InputStream in)
  380.             throws ArchiveException {
  381.         return createArchiveInputStream(archiverName, in, entryEncoding);
  382.     }

  383.     @SuppressWarnings("unchecked")
  384.     @Override
  385.     public <I extends ArchiveInputStream<? extends ArchiveEntry>> I createArchiveInputStream(final String archiverName, final InputStream in,
  386.             final String actualEncoding) throws ArchiveException {

  387.         if (archiverName == null) {
  388.             throw new IllegalArgumentException("Archiver name must not be null.");
  389.         }

  390.         if (in == null) {
  391.             throw new IllegalArgumentException("InputStream must not be null.");
  392.         }

  393.         if (AR.equalsIgnoreCase(archiverName)) {
  394.             return (I) new ArArchiveInputStream(in);
  395.         }
  396.         if (ARJ.equalsIgnoreCase(archiverName)) {
  397.             if (actualEncoding != null) {
  398.                 return (I) new ArjArchiveInputStream(in, actualEncoding);
  399.             }
  400.             return (I) new ArjArchiveInputStream(in);
  401.         }
  402.         if (ZIP.equalsIgnoreCase(archiverName)) {
  403.             if (actualEncoding != null) {
  404.                 return (I) new ZipArchiveInputStream(in, actualEncoding);
  405.             }
  406.             return (I) new ZipArchiveInputStream(in);
  407.         }
  408.         if (TAR.equalsIgnoreCase(archiverName)) {
  409.             if (actualEncoding != null) {
  410.                 return (I) new TarArchiveInputStream(in, actualEncoding);
  411.             }
  412.             return (I) new TarArchiveInputStream(in);
  413.         }
  414.         if (JAR.equalsIgnoreCase(archiverName) || APK.equalsIgnoreCase(archiverName)) {
  415.             if (actualEncoding != null) {
  416.                 return (I) new JarArchiveInputStream(in, actualEncoding);
  417.             }
  418.             return (I) new JarArchiveInputStream(in);
  419.         }
  420.         if (CPIO.equalsIgnoreCase(archiverName)) {
  421.             if (actualEncoding != null) {
  422.                 return (I) new CpioArchiveInputStream(in, actualEncoding);
  423.             }
  424.             return (I) new CpioArchiveInputStream(in);
  425.         }
  426.         if (DUMP.equalsIgnoreCase(archiverName)) {
  427.             if (actualEncoding != null) {
  428.                 return (I) new DumpArchiveInputStream(in, actualEncoding);
  429.             }
  430.             return (I) new DumpArchiveInputStream(in);
  431.         }
  432.         if (SEVEN_Z.equalsIgnoreCase(archiverName)) {
  433.             throw new StreamingNotSupportedException(SEVEN_Z);
  434.         }

  435.         final ArchiveStreamProvider archiveStreamProvider = getArchiveInputStreamProviders().get(toKey(archiverName));
  436.         if (archiveStreamProvider != null) {
  437.             return archiveStreamProvider.createArchiveInputStream(archiverName, in, actualEncoding);
  438.         }

  439.         throw new ArchiveException("Archiver: " + archiverName + " not found.");
  440.     }

  441.     /**
  442.      * Creates an archive output stream from an archiver name and an output stream.
  443.      *
  444.      * @param <O>          The {@link ArchiveOutputStream} type.
  445.      * @param archiverName the archive name, i.e. {@value #AR}, {@value #ZIP}, {@value #TAR}, {@value #JAR} or {@value #CPIO}
  446.      * @param out          the output stream
  447.      * @return the archive output stream
  448.      * @throws ArchiveException               if the archiver name is not known
  449.      * @throws StreamingNotSupportedException if the format cannot be written to a stream
  450.      * @throws IllegalArgumentException       if the archiver name or stream is null
  451.      */
  452.     public <O extends ArchiveOutputStream<? extends ArchiveEntry>> O createArchiveOutputStream(final String archiverName, final OutputStream out)
  453.             throws ArchiveException {
  454.         return createArchiveOutputStream(archiverName, out, entryEncoding);
  455.     }

  456.     @SuppressWarnings("unchecked")
  457.     @Override
  458.     public <O extends ArchiveOutputStream<? extends ArchiveEntry>> O createArchiveOutputStream(final String archiverName, final OutputStream out,
  459.             final String actualEncoding) throws ArchiveException {
  460.         if (archiverName == null) {
  461.             throw new IllegalArgumentException("Archiver name must not be null.");
  462.         }
  463.         if (out == null) {
  464.             throw new IllegalArgumentException("OutputStream must not be null.");
  465.         }

  466.         if (AR.equalsIgnoreCase(archiverName)) {
  467.             return (O) new ArArchiveOutputStream(out);
  468.         }
  469.         if (ZIP.equalsIgnoreCase(archiverName)) {
  470.             final ZipArchiveOutputStream zip = new ZipArchiveOutputStream(out);
  471.             if (actualEncoding != null) {
  472.                 zip.setEncoding(actualEncoding);
  473.             }
  474.             return (O) zip;
  475.         }
  476.         if (TAR.equalsIgnoreCase(archiverName)) {
  477.             if (actualEncoding != null) {
  478.                 return (O) new TarArchiveOutputStream(out, actualEncoding);
  479.             }
  480.             return (O) new TarArchiveOutputStream(out);
  481.         }
  482.         if (JAR.equalsIgnoreCase(archiverName)) {
  483.             if (actualEncoding != null) {
  484.                 return (O) new JarArchiveOutputStream(out, actualEncoding);
  485.             }
  486.             return (O) new JarArchiveOutputStream(out);
  487.         }
  488.         if (CPIO.equalsIgnoreCase(archiverName)) {
  489.             if (actualEncoding != null) {
  490.                 return (O) new CpioArchiveOutputStream(out, actualEncoding);
  491.             }
  492.             return (O) new CpioArchiveOutputStream(out);
  493.         }
  494.         if (SEVEN_Z.equalsIgnoreCase(archiverName)) {
  495.             throw new StreamingNotSupportedException(SEVEN_Z);
  496.         }

  497.         final ArchiveStreamProvider archiveStreamProvider = getArchiveOutputStreamProviders().get(toKey(archiverName));
  498.         if (archiveStreamProvider != null) {
  499.             return archiveStreamProvider.createArchiveOutputStream(archiverName, out, actualEncoding);
  500.         }

  501.         throw new ArchiveException("Archiver: " + archiverName + " not found.");
  502.     }

  503.     public SortedMap<String, ArchiveStreamProvider> getArchiveInputStreamProviders() {
  504.         if (archiveInputStreamProviders == null) {
  505.             archiveInputStreamProviders = Collections.unmodifiableSortedMap(findAvailableArchiveInputStreamProviders());
  506.         }
  507.         return archiveInputStreamProviders;
  508.     }

  509.     public SortedMap<String, ArchiveStreamProvider> getArchiveOutputStreamProviders() {
  510.         if (archiveOutputStreamProviders == null) {
  511.             archiveOutputStreamProviders = Collections.unmodifiableSortedMap(findAvailableArchiveOutputStreamProviders());
  512.         }
  513.         return archiveOutputStreamProviders;
  514.     }

  515.     /**
  516.      * Gets the encoding to use for arj, jar, ZIP, dump, cpio and tar files, or null for the archiver default.
  517.      *
  518.      * @return entry encoding, or null for the archiver default
  519.      * @since 1.5
  520.      */
  521.     public String getEntryEncoding() {
  522.         return entryEncoding;
  523.     }

  524.     @Override
  525.     public Set<String> getInputStreamArchiveNames() {
  526.         return Sets.newHashSet(AR, ARJ, ZIP, TAR, JAR, CPIO, DUMP, SEVEN_Z);
  527.     }

  528.     @Override
  529.     public Set<String> getOutputStreamArchiveNames() {
  530.         return Sets.newHashSet(AR, ZIP, TAR, JAR, CPIO, SEVEN_Z);
  531.     }

  532.     /**
  533.      * Sets the encoding to use for arj, jar, ZIP, dump, cpio and tar files. Use null for the archiver default.
  534.      *
  535.      * @param entryEncoding the entry encoding, null uses the archiver default.
  536.      * @since 1.5
  537.      * @deprecated 1.10 use {@link #ArchiveStreamFactory(String)} to specify the encoding
  538.      */
  539.     @Deprecated
  540.     public void setEntryEncoding(final String entryEncoding) {
  541.         this.entryEncoding = entryEncoding;
  542.     }

  543. }