diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java index 3ec22574c3..43ee335ed1 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java @@ -639,8 +639,8 @@ public void handle(final ClassicHttpRequest request, Assertions.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(), reqWrapper.getUri()); - assertThat(values.poll(), CoreMatchers.equalTo("snappy-raw, snappy-framed, xz, bzip2, lz4-framed, deflate64, br, lzma, zstd, lz4-block, deflate, gz, z, pack200")); - assertThat(values.poll(), CoreMatchers.equalTo("snappy-raw, snappy-framed, xz, bzip2, lz4-framed, deflate64, br, lzma, zstd, lz4-block, deflate, gz, z, pack200")); + assertThat(values.poll(), CoreMatchers.equalTo("snappy-raw, xz, snappy-framed, bzip2, lz4-framed, deflate64, br, lzma, zstd, lz4-block, gz, deflate, z, pack200")); + assertThat(values.poll(), CoreMatchers.equalTo("snappy-raw, xz, snappy-framed, bzip2, lz4-framed, deflate64, br, lzma, zstd, lz4-block, gz, deflate, z, pack200")); assertThat(values.poll(), CoreMatchers.nullValue()); } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliDecompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliDecompressingEntity.java index c37129431c..f55e3a6895 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliDecompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliDecompressingEntity.java @@ -34,7 +34,7 @@ * * @see GzipDecompressingEntity * @since 5.2 - * @deprecated + * @deprecated Use {@link CompressorFactory} for handling Brotli decompression. */ @Deprecated public class BrotliDecompressingEntity extends DecompressingEntity { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliInputStreamFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliInputStreamFactory.java index 2615043255..e2f99c717a 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliInputStreamFactory.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/BrotliInputStreamFactory.java @@ -37,7 +37,7 @@ * {@link InputStreamFactory} for handling Brotli Content Coded responses. * * @since 5.2 - * @deprecated + * @deprecated Use {@link CompressorFactory} for handling Brotli compression. */ @Deprecated @Contract(threading = ThreadingBehavior.STATELESS) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressingEntity.java index 1adc19c54e..2f02e80824 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressingEntity.java @@ -30,6 +30,7 @@ import java.io.InputStream; import java.io.OutputStream; +import org.apache.commons.compress.compressors.CompressorException; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.HttpEntityWrapper; import org.apache.hc.core5.util.Args; @@ -45,7 +46,7 @@ * reading the content directly through {@link #getContent()} as the content is always compressed * during write operations.

* - * @since 5.4 + * @since 5.5 */ public class CompressingEntity extends HttpEntityWrapper { @@ -76,16 +77,6 @@ public String getContentEncoding() { return contentEncoding; } - /** - * Returns the length of the wrapped entity. As the content is compressed, - * this will return the length of the wrapped entity's compressed data. - * - * @return the length of the compressed content, or {@code -1} if unknown. - */ - @Override - public long getContentLength() { - return super.getContentLength(); - } /** * Returns whether the entity is chunked. This is determined by the wrapped entity. @@ -97,6 +88,7 @@ public boolean isChunked() { return super.isChunked(); } + /** * This method is unsupported because the content is meant to be compressed during the * {@link #writeTo(OutputStream)} operation. @@ -121,7 +113,12 @@ public void writeTo(final OutputStream outStream) throws IOException { Args.notNull(outStream, "Output stream"); // Get the compressor based on the specified content encoding - final OutputStream compressorStream = CompressorFactory.INSTANCE.getCompressorOutputStream(contentEncoding, outStream); + final OutputStream compressorStream; + try { + compressorStream = CompressorFactory.INSTANCE.getCompressorOutputStream(contentEncoding, outStream); + } catch (final CompressorException e) { + throw new IOException("Error initializing decompression stream", e); + } if (compressorStream != null) { // Write compressed data diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressorFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressorFactory.java index 5d1bffaffc..41a4d0248e 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressorFactory.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressorFactory.java @@ -29,8 +29,6 @@ import java.io.InputStream; import java.io.OutputStream; -import java.util.Collections; -import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -38,6 +36,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +import org.apache.commons.compress.compressors.CompressorException; import org.apache.commons.compress.compressors.CompressorStreamFactory; import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream; import org.apache.commons.compress.compressors.deflate.DeflateParameters; @@ -62,6 +61,8 @@ *

* This class is thread-safe and uses {@link AtomicReference} to cache the available input and output stream providers. *

+ * + * @since 5.5 */ public class CompressorFactory { @@ -76,22 +77,13 @@ public class CompressorFactory { private final AtomicReference> outputProvidersCache = new AtomicReference<>(); private final Map formattedNameCache = new ConcurrentHashMap<>(); - private static final Map COMPRESSION_ALIASES; - static { - final Map aliases = new HashMap<>(); - aliases.put("gzip", "gz"); - aliases.put("x-gzip", "gz"); - aliases.put("compress", "z"); - COMPRESSION_ALIASES = Collections.unmodifiableMap(aliases); - } - /** * Returns a set of available input stream compression providers. * * @return a set of available input stream compression providers in lowercase. */ public Set getAvailableInputProviders() { - return getAvailableProviders(inputProvidersCache, false); + return inputProvidersCache.updateAndGet(existing -> existing != null ? existing : fetchAvailableInputProviders()); } /** @@ -100,7 +92,7 @@ public Set getAvailableInputProviders() { * @return a set of available output stream compression providers in lowercase. */ public Set getAvailableOutputProviders() { - return getAvailableProviders(outputProvidersCache, true); + return outputProvidersCache.updateAndGet(existing -> existing != null ? existing : fetchAvailableOutputProviders()); } /** @@ -119,29 +111,35 @@ public String getFormattedName(final String name) { return null; } final String lowerCaseName = name.toLowerCase(Locale.ROOT); - return formattedNameCache.computeIfAbsent(lowerCaseName, key -> COMPRESSION_ALIASES.getOrDefault(key, key)); + return formattedNameCache.computeIfAbsent(lowerCaseName, key -> { + if ("gzip".equals(key) || "x-gzip".equals(key)) { + return "gz"; + } else if ("compress".equals(key)) { + return "z"; + } + return key; + }); } - /** * Creates an input stream for the specified compression format and decompresses the provided input stream. *

- * This method uses the specified compression name to decompress the input stream and supports the "nowrap" option + * This method uses the specified compression name to decompress the input stream and supports the "noWrap" option * for deflate streams. *

* * @param name the compression format. * @param inputStream the input stream to decompress. - * @param nowrap if true, disables the zlib header and trailer for deflate streams. + * @param noWrap if true, disables the zlib header and trailer for deflate streams. * @return the decompressed input stream, or the original input stream if the format is not supported. */ - public InputStream getCompressorInputStream(final String name, final InputStream inputStream, final boolean nowrap) { + public InputStream getCompressorInputStream(final String name, final InputStream inputStream, final boolean noWrap) throws CompressorException { Args.notNull(inputStream, "InputStream"); Args.notNull(name, "name"); final String formattedName = getFormattedName(name); return isSupported(formattedName, false) - ? createCompressorInputStream(formattedName, inputStream, nowrap) + ? createCompressorInputStream(formattedName, inputStream, noWrap) : inputStream; } @@ -152,30 +150,15 @@ public InputStream getCompressorInputStream(final String name, final InputStream * @param outputStream the output stream to compress. * @return the compressed output stream, or the original output stream if the format is not supported. */ - public OutputStream getCompressorOutputStream(final String name, final OutputStream outputStream) { + public OutputStream getCompressorOutputStream(final String name, final OutputStream outputStream) throws CompressorException { final String formattedName = getFormattedName(name); return isSupported(formattedName, true) ? createCompressorOutputStream(formattedName, outputStream) : outputStream; - } - /** - * Compresses the provided HTTP entity using the specified compression format. - * - * @param entity the HTTP entity to compress. - * @param contentEncoding the compression format. - * @return a compressed {@link HttpEntity}, or {@code null} if the compression format is unsupported. - */ - public HttpEntity compressEntity(final HttpEntity entity, final String contentEncoding) { - Args.notNull(entity, "Entity"); - Args.notNull(contentEncoding, "Content Encoding"); - if (!isSupported(contentEncoding, true)) { - LOG.warn("Unsupported compression type: {}", contentEncoding); - return null; - } - return new CompressingEntity(entity, contentEncoding); } + /** * Decompresses the provided HTTP entity using the specified compression format. * @@ -192,103 +175,108 @@ public HttpEntity decompressEntity(final HttpEntity entity, final String content * * @param entity the HTTP entity to decompress. * @param contentEncoding the compression format. - * @param nowrap if true, disables the zlib header and trailer for deflate streams. + * @param noWrap if true, disables the zlib header and trailer for deflate streams. * @return a decompressed {@link HttpEntity}, or {@code null} if the compression format is unsupported. */ - public HttpEntity decompressEntity(final HttpEntity entity, final String contentEncoding, final boolean nowrap) { + public HttpEntity decompressEntity(final HttpEntity entity, final String contentEncoding, final boolean noWrap) { Args.notNull(entity, "Entity"); Args.notNull(contentEncoding, "Content Encoding"); if (!isSupported(contentEncoding, false)) { LOG.warn("Unsupported decompression type: {}", contentEncoding); return null; } - return new DecompressEntity(entity, contentEncoding, nowrap); + return new DecompressEntity(entity, contentEncoding, noWrap); } /** - * Creates a compressor input stream for the given compression format and input stream. - *

- * This method handles the special case for deflate compression where the zlib header can be skipped. - *

+ * Compresses the provided HTTP entity using the specified compression format. * - * @param name the compression format. - * @param inputStream the input stream to decompress. - * @param nowrap if true, disables the zlib header and trailer for deflate streams. - * @return a decompressed input stream, or null if an error occurs. + * @param entity the HTTP entity to compress. + * @param contentEncoding the compression format. + * @return a compressed {@link HttpEntity}, or {@code null} if the compression format is unsupported. */ - private InputStream createCompressorInputStream(final String name, final InputStream inputStream, final boolean nowrap) { - try { - if ("deflate".equalsIgnoreCase(name)) { - final DeflateParameters parameters = new DeflateParameters(); - parameters.setWithZlibHeader(nowrap); - return new DeflateCompressorInputStream(inputStream, parameters); - } - return compressorStreamFactory.createCompressorInputStream(name, inputStream, true); - } catch (final Exception ex) { - LOG.warn("Could not create compressor {} input stream", name, ex); + public HttpEntity compressEntity(final HttpEntity entity, final String contentEncoding) { + Args.notNull(entity, "Entity"); + Args.notNull(contentEncoding, "Content Encoding"); + if (!isSupported(contentEncoding, true)) { + LOG.warn("Unsupported compression type: {}", contentEncoding); return null; } + return new CompressingEntity(entity, contentEncoding); } /** - * Determines if the specified compression format is supported for either input or output streams. + * Fetches the available input stream compression providers from Commons Compress. * - * @param name the compression format. - * @param isOutput if true, checks if the format is supported for output; otherwise, checks for input support. - * @return true if the format is supported, false otherwise. + * @return a set of available input stream compression providers in lowercase. */ - private boolean isSupported(final String name, final boolean isOutput) { - final String formattedName = getFormattedName(name); - return isOutput - ? getAvailableOutputProviders().contains(formattedName) - : getAvailableInputProviders().contains(formattedName); + private Set fetchAvailableInputProviders() { + final Set inputNames = compressorStreamFactory.getInputStreamCompressorNames(); + return inputNames.stream() + .map(String::toLowerCase) + .collect(Collectors.toSet()); } /** - * Creates a compressor output stream for the given compression format and output stream. + * Fetches the available output stream compression providers from Commons Compress. * - * @param name the compression format. - * @param outputStream the output stream to compress. - * @return a compressed output stream, or null if an error occurs. + * @return a set of available output stream compression providers in lowercase. */ - private OutputStream createCompressorOutputStream(final String name, final OutputStream outputStream) { - try { - return compressorStreamFactory.createCompressorOutputStream(name, outputStream); - } catch (final Exception ex) { - LOG.warn("Could not create compressor {} output stream", name, ex); - - return null; - } + private Set fetchAvailableOutputProviders() { + final Set outputNames = compressorStreamFactory.getOutputStreamCompressorNames(); + return outputNames.stream() + .map(String::toLowerCase) + .collect(Collectors.toSet()); } /** - * Retrieves the available compression providers for input or output streams. + * Creates a compressor input stream for the given compression format and input stream. *

- * This method uses a cache to avoid redundant lookups and ensures the providers are formatted in lowercase. + * This method handles the special case for deflate compression where the zlib header can be optionally included. + * The noWrap parameter directly controls the behavior of the zlib header: + * - If noWrap is {@code true}, the deflate stream is processed without zlib headers (raw Deflate). + * - If noWrap is {@code false}, the deflate stream includes the zlib header. *

* - * @param cache the cache that stores the available providers. - * @param isOutput if true, retrieves available providers for output streams; otherwise, for input streams. - * @return a set of available compression providers in lowercase. + * @param name the compression format (e.g., "gzip", "deflate"). + * @param inputStream the input stream to decompress; must not be {@code null}. + * @param noWrap if {@code true}, disables the zlib header and trailer for deflate streams (raw Deflate). + * @return a decompressed input stream, or {@code null} if an error occurs during stream creation. + * @throws CompressorException if an error occurs while creating the compressor input stream or if the compression format is unsupported. */ - private Set getAvailableProviders(final AtomicReference> cache, final boolean isOutput) { - return cache.updateAndGet(existing -> existing != null ? existing : fetchAvailableProviders(isOutput)); + private InputStream createCompressorInputStream(final String name, final InputStream inputStream, final boolean noWrap) throws CompressorException { + if ("deflate".equalsIgnoreCase(name)) { + final DeflateParameters parameters = new DeflateParameters(); + parameters.setWithZlibHeader(noWrap); + return new DeflateCompressorInputStream(inputStream, parameters); + } + return compressorStreamFactory.createCompressorInputStream(name, inputStream, true); } /** - * Fetches the available compression providers by querying the {@link CompressorStreamFactory}. + * Creates a compressor output stream for the given compression format and output stream. * - * @param isOutput if true, fetches available providers for output streams; otherwise, for input streams. - * @return a set of available compression providers in lowercase. + * @param name the compression format. + * @param outputStream the output stream to compress. + * @return a compressed output stream, or null if an error occurs. + * @throws CompressorException if an error occurs while creating the compressor output stream. */ - private Set fetchAvailableProviders(final boolean isOutput) { - return (isOutput - ? CompressorStreamFactory.findAvailableCompressorOutputStreamProviders() - : CompressorStreamFactory.findAvailableCompressorInputStreamProviders()) - .keySet().stream() - .map(String::toLowerCase) - .collect(Collectors.collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet)); + private OutputStream createCompressorOutputStream(final String name, final OutputStream outputStream) throws CompressorException { + return compressorStreamFactory.createCompressorOutputStream(name, outputStream); + } + + /** + * Determines if the specified compression format is supported for either input or output streams. + * + * @param name the compression format. + * @param isOutput if true, checks if the format is supported for output; otherwise, checks for input support. + * @return true if the format is supported, false otherwise. + */ + private boolean isSupported(final String name, final boolean isOutput) { + final Set availableProviders = isOutput ? getAvailableOutputProviders() : getAvailableInputProviders(); + return availableProviders.contains(name); } } + diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressEntity.java index c97e854e81..38771e7ce3 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressEntity.java @@ -30,28 +30,35 @@ import java.io.InputStream; import java.io.OutputStream; +import org.apache.commons.io.IOUtils; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.HttpEntityWrapper; import org.apache.hc.core5.util.Args; - /** * An {@link HttpEntity} wrapper that decompresses the content of the wrapped entity. - * This class supports different compression types and can handle both standard - * compression (e.g., gzip, deflate) and variations that require a custom handling (e.g., nowrap). + * This class supports various compression types such as "gzip", "deflate", and others. + * It also handles variations like noWrap, where zlib headers and trailers are omitted. + * + *

+ * Decompression is performed lazily through a {@link LazyDecompressInputStream}, which + * initializes the decompression stream only when the content is requested. + *

* - *

Decompression is performed using a {@link LazyDecompressInputStream} that - * applies decompression lazily when content is requested.

+ *

+ * Content Length: Since the content is being decompressed, the exact content length is + * unknown, and as such, this class returns the content length of the wrapped entity. + *

* - * @since 5.4 + *

+ * Note: This class is not thread-safe. If multiple threads access an instance of this class concurrently, + * they must synchronize on the instance to ensure correct behavior. + *

+ * + * @since 5.5 */ public class DecompressEntity extends HttpEntityWrapper { - /** - * Default buffer size used during decompression. - */ - private static final int BUFFER_SIZE = 1024 * 2; - /** * The content input stream, initialized lazily during the first read. */ @@ -63,25 +70,25 @@ public class DecompressEntity extends HttpEntityWrapper { private final String compressionType; /** - * The flag indicating if decompression should skip certain headers (nowrap). + * The flag indicating if decompression should skip certain headers (noWrap). */ - private final boolean nowrap; + private final boolean noWrap; /** - * Constructs a new {@link DecompressEntity} with the specified compression type and nowrap setting. + * Constructs a new {@link DecompressEntity} with the specified compression type and noWrap setting. * * @param wrapped the non-null {@link HttpEntity} to be wrapped. * @param compressionType the compression type (e.g., "gzip", "deflate"). - * @param nowrap whether to decompress without headers for certain compression formats. + * @param noWrap whether to decompress without headers for certain compression formats. */ - public DecompressEntity(final HttpEntity wrapped, final String compressionType, final boolean nowrap) { + public DecompressEntity(final HttpEntity wrapped, final String compressionType, final boolean noWrap) { super(wrapped); this.compressionType = compressionType; - this.nowrap = nowrap; + this.noWrap = noWrap; } /** - * Constructs a new {@link DecompressEntity} with the specified compression type, defaulting to no nowrap handling. + * Constructs a new {@link DecompressEntity} with the specified compression type, defaulting to no noWrap handling. * * @param wrapped the non-null {@link HttpEntity} to be wrapped. * @param compressionType the compression type (e.g., "gzip", "deflate"). @@ -98,7 +105,7 @@ public DecompressEntity(final HttpEntity wrapped, final String compressionType) * @throws IOException if an error occurs during decompression. */ private InputStream getDecompressingStream() throws IOException { - return new LazyDecompressInputStream(super.getContent(), compressionType, nowrap); + return new LazyDecompressInputStream(super.getContent(), compressionType, noWrap); } /** @@ -129,11 +136,7 @@ public InputStream getContent() throws IOException { public void writeTo(final OutputStream outStream) throws IOException { Args.notNull(outStream, "Output stream"); try (InputStream inStream = getContent()) { - final byte[] buffer = new byte[BUFFER_SIZE]; - int l; - while ((l = inStream.read(buffer)) != -1) { - outStream.write(buffer, 0, l); - } + IOUtils.copy(inStream, outStream); } } @@ -146,15 +149,4 @@ public void writeTo(final OutputStream outStream) throws IOException { public String getContentEncoding() { return compressionType; } - - /** - * Returns the length of the decompressed content. Since the content is being decompressed, - * the exact length is unknown and this method returns the length of the wrapped entity. - * - * @return the content length, or {@code -1} if unknown. - */ - @Override - public long getContentLength() { - return super.getContentLength(); - } } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateDecompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateDecompressingEntity.java index 4c9ab3adb1..3395eb8904 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateDecompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateDecompressingEntity.java @@ -43,7 +43,7 @@ * @see GzipDecompressingEntity * * @since 4.1 - * @deprecated + * @deprecated Use {@link DecompressEntity} or {@link CompressorFactory} for decompression handling. */ @Deprecated public class DeflateDecompressingEntity extends DecompressingEntity { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStream.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStream.java index f172b316a6..68c44b8858 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStream.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStream.java @@ -38,7 +38,7 @@ /** * Deflates an input stream. This class includes logic needed for various RFCs in order * to reasonably implement the "deflate" compression algorithm. - * @deprecated + * @deprecated Use {@link CompressorFactory} for handling Deflate compression. */ @Deprecated public class DeflateInputStream extends FilterInputStream { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStreamFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStreamFactory.java index 86743ac806..d930b761c7 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStreamFactory.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DeflateInputStreamFactory.java @@ -37,7 +37,7 @@ * {@link InputStreamFactory} for handling Deflate Content Coded responses. * * @since 5.0 - * @deprecated + * @deprecated Use {@link CompressorFactory}. */ @Deprecated @Contract(threading = ThreadingBehavior.STATELESS) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GZIPInputStreamFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GZIPInputStreamFactory.java index 7ecfc03a1b..32d59b02dc 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GZIPInputStreamFactory.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GZIPInputStreamFactory.java @@ -38,7 +38,7 @@ * {@link InputStreamFactory} for handling GZIPContent Coded responses. * * @since 5.0 - * @deprecated + * @deprecated Use {@link CompressorFactory#getCompressorInputStream(String, InputStream, boolean)} instead. */ @Deprecated @Contract(threading = ThreadingBehavior.STATELESS) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipCompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipCompressingEntity.java index f7ea0d647c..822faf2eea 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipCompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipCompressingEntity.java @@ -40,7 +40,7 @@ * * * @since 4.0 - * @deprecated + * @deprecated Use {@link CompressorFactory#compressEntity(HttpEntity, String)} to handle compression. */ @Deprecated public class GzipCompressingEntity extends HttpEntityWrapper { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipDecompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipDecompressingEntity.java index 5d12df62c4..396e498052 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipDecompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/GzipDecompressingEntity.java @@ -33,7 +33,7 @@ * gzip Content Coded responses. * * @since 4.1 - * @deprecated + * @deprecated Use {@link CompressorFactory} for handling Gzip decompression. */ @Deprecated public class GzipDecompressingEntity extends DecompressingEntity { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/InputStreamFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/InputStreamFactory.java index a9f0618763..8bd220e402 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/InputStreamFactory.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/InputStreamFactory.java @@ -33,7 +33,7 @@ * Factory for decorated {@link InputStream}s. * * @since 4.4 - * @deprecated + * @deprecated Use {@link CompressorFactory} to retrieve appropriate {@link InputStream}s for compression handling. */ @Deprecated public interface InputStreamFactory { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressInputStream.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressInputStream.java index d049795d1a..ad6e1b1473 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressInputStream.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressInputStream.java @@ -31,6 +31,7 @@ import java.io.InputStream; import java.io.UncheckedIOException; +import org.apache.commons.compress.compressors.CompressorException; import org.apache.hc.core5.io.Closer; @@ -42,7 +43,7 @@ *

This implementation delays the creation of the decompression stream until it is required, optimizing * the performance when the stream may not be read immediately or at all.

* - * @since 5.4 + * @since 5.5 */ public class LazyDecompressInputStream extends FilterInputStream { @@ -57,26 +58,26 @@ public class LazyDecompressInputStream extends FilterInputStream { private final String compressionType; /** - * The flag indicating if decompression should skip certain headers (nowrap). + * The flag indicating if decompression should skip certain headers (noWrap). */ - private final boolean nowrap; + private final boolean noWrap; /** - * Constructs a new {@link LazyDecompressInputStream} that applies the specified compression type and nowrap setting. + * Constructs a new {@link LazyDecompressInputStream} that applies the specified compression type and noWrap setting. * * @param wrappedStream the non-null {@link InputStream} to be wrapped and decompressed. * @param compressionType the compression type (e.g., "gzip", "deflate"). - * @param nowrap whether to decompress without headers for certain compression formats. + * @param noWrap whether to decompress without headers for certain compression formats. */ - public LazyDecompressInputStream(final InputStream wrappedStream, final String compressionType, final boolean nowrap) { + public LazyDecompressInputStream(final InputStream wrappedStream, final String compressionType, final boolean noWrap) { super(wrappedStream); this.compressionType = compressionType; - this.nowrap = nowrap; + this.noWrap = noWrap; } /** * Constructs a new {@link LazyDecompressInputStream} that applies the specified compression type, - * defaulting to no nowrap handling. + * defaulting to no noWrap handling. * * @param wrappedStream the non-null {@link InputStream} to be wrapped and decompressed. * @param compressionType the compression type (e.g., "gzip", "deflate"). @@ -86,14 +87,18 @@ public LazyDecompressInputStream(final InputStream wrappedStream, final String c } /** - * Initializes the decompression wrapper stream lazily, based on the compression type and nowrap flag. + * Initializes the decompression wrapper stream lazily, based on the compression type and noWrap flag. * * @return the initialized decompression stream. * @throws IOException if an error occurs during initialization. */ private InputStream initWrapper() throws IOException { if (wrapperStream == null) { - wrapperStream = CompressorFactory.INSTANCE.getCompressorInputStream(compressionType, in, nowrap); + try { + wrapperStream = CompressorFactory.INSTANCE.getCompressorInputStream(compressionType, in, noWrap); + } catch (final CompressorException e) { + throw new IOException("Error initializing decompression stream", e); + } } return wrapperStream; } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressingInputStream.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressingInputStream.java index 85d67bb498..622df3db2f 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressingInputStream.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressingInputStream.java @@ -35,7 +35,7 @@ /** * Lazy initializes from an {@link InputStream} wrapper. - * @deprecated + * @deprecated Use {@link LazyDecompressInputStream} */ @Deprecated class LazyDecompressingInputStream extends FilterInputStream {