2929
3030import java .io .IOException ;
3131import java .io .InputStream ;
32+ import java .util .Collections ;
33+ import java .util .EnumMap ;
3234import java .util .Locale ;
35+ import java .util .Map ;
3336
3437import org .apache .commons .compress .compressors .CompressorException ;
3538import org .apache .commons .compress .compressors .CompressorStreamFactory ;
3942import org .apache .hc .core5 .annotation .ThreadingBehavior ;
4043
4144/**
42- * {@link InputStreamFactory} backed by
43- * <a href="https://commons.apache.org/proper/commons-compress/">Apache Commons Compress</a>.
45+ * A factory for creating InputStream instances, utilizing Apache Commons Compress.
46+ * This class is compiled with Commons Compress as an optional dependency, loading
47+ * only when the library is present at runtime, avoiding mandatory inclusion in
48+ * downstream builds.
4449 * <p>
45- * The class is compiled against Commons Compress but lives behind an <i>optional</i>
46- * dependency. At run-time it will only be loaded when the library is present,
47- * therefore callers may rely on it without pulling Commons Compress into every
48- * downstream build.
49- * </p>
50- *
51- * <h4>Run-time guards</h4>
52- * Some encodings (e.g. {@code br}, {@code zstd}, {@code xz/lzma})
53- * depend on native helper JARs. {@link #runtimeAvailable(String)} performs a
54- * lightweight {@code Class.forName} probe so we register such codecs only when
55- * the helper is on the class-path.
50+ * <p>
51+ * Some encodings require native helper JARs; runtime availability is checked
52+ * using a lightweight Class.forName probe to register codecs only when helpers
53+ * are present.
5654 *
5755 * @since 5.6
5856 */
5957@ Internal
6058@ Contract (threading = ThreadingBehavior .STATELESS )
6159final class CommonsCompressDecoderFactory implements InputStreamFactory {
6260
61+
62+ /**
63+ * Map of codings that need extra JARs → the fully‐qualified class we test for
64+ */
65+ private static final Map <ContentCoding , String > REQUIRED_CLASS_NAME ;
66+
67+ static {
68+ final Map <ContentCoding , String > m = new EnumMap <>(ContentCoding .class );
69+ m .put (ContentCoding .BROTLI , "org.brotli.dec.BrotliInputStream" );
70+ m .put (ContentCoding .ZSTD , "com.github.luben.zstd.ZstdInputStream" );
71+ m .put (ContentCoding .XZ , "org.tukaani.xz.XZInputStream" );
72+ m .put (ContentCoding .LZMA , "org.tukaani.xz.XZInputStream" );
73+ REQUIRED_CLASS_NAME = Collections .unmodifiableMap (m );
74+ }
75+
6376 private final String encoding ;
6477
6578 CommonsCompressDecoderFactory (final String encoding ) {
@@ -82,37 +95,19 @@ public InputStream create(final InputStream source) throws IOException {
8295 }
8396 }
8497
85- private enum Probe {
86- BR (ContentCoding .BROTLI .token (), "org.brotli.dec.BrotliInputStream" ),
87- ZSTD (ContentCoding .ZSTD .token (), "com.github.luben.zstd.ZstdInputStream" ),
88- XZ (ContentCoding .XZ .token (), "org.tukaani.xz.XZInputStream" ),
89- LZMA (ContentCoding .LZMA .token (), "org.tukaani.xz.XZInputStream" );
9098
91- final String enc , probeClass ;
92-
93- Probe (final String enc , final String probeClass ) {
94- this .enc = enc ;
95- this .probeClass = probeClass ;
96- }
97-
98- static String helperFor (final String enc ) {
99- for (final Probe p : values ()) {
100- if (p .enc .equals (enc )) {
101- return p .probeClass ;
102- }
103- }
104- return null ;
99+ static boolean runtimeAvailable (final String token ) {
100+ final ContentCoding coding = ContentCoding .fromToken (token );
101+ if (coding == null ) {
102+ return true ;
105103 }
106- }
107-
108- static boolean runtimeAvailable (final String enc ) {
109- final String probe = Probe .helperFor (enc .toLowerCase (Locale .ROOT ));
110- if (probe == null ) {
104+ final String helper = REQUIRED_CLASS_NAME .get (coding );
105+ if (helper == null ) {
106+ // no extra JAR needed
111107 return true ;
112108 }
113109 try {
114- Class .forName (
115- probe , false ,
110+ Class .forName (helper , false ,
116111 CommonsCompressDecoderFactory .class .getClassLoader ());
117112 return true ;
118113 } catch (final ClassNotFoundException | LinkageError ex ) {
0 commit comments