diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientBuilder.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientBuilder.java index db474ae89..4f9d83ec2 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientBuilder.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientBuilder.java @@ -98,6 +98,13 @@ public interface TestClientBuilder { throw new UnsupportedOperationException("Operation not supported by " + getProtocolLevel()); } + /** + * Configures whether the client builder should wrap requests and responses. + * + * @param noWrap {@code true} to disable wrapping; {@code false} to enable wrapping. + * @return this builder instance. + * @since 5.5 + */ default TestClientBuilder setNoWrap(boolean noWrap) { return this; } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientResources.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientResources.java index cfc1d9889..9b1ed3088 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientResources.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/sync/TestClientResources.java @@ -111,6 +111,14 @@ public class TestClientResources implements AfterEachCallback { return client; } + /** + * Creates a configured {@link TestClient} instance. + * + * @param noWrap {@code true} to disable wrapping; {@code false} to enable wrapping. + * @return a {@link TestClient} instance. + * @throws Exception if an error occurs during client creation. + * @since 5.5 + */ public TestClient client(final boolean noWrap) throws Exception { clientBuilder.setNoWrap(noWrap); return client(); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/AbstractIntegrationTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/AbstractIntegrationTestBase.java index 652316721..4c31f6dd7 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/AbstractIntegrationTestBase.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/AbstractIntegrationTestBase.java @@ -78,6 +78,14 @@ abstract class AbstractIntegrationTestBase { return testResources.client(); } + /** + * Retrieves a {@link TestClient} instance configured with the specified wrapping option. + * + * @param noWrap {@code true} to disable wrapping; {@code false} to enable wrapping. + * @return a {@link TestClient} instance. + * @throws Exception if an error occurs during client retrieval or configuration. + * @since 5.5 + */ public TestClient client(final boolean noWrap) throws Exception { return testResources.client(noWrap); } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/compress/CompressedResponseHandlingExample.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/compress/CompressedResponseHandlingExample.java index 4ad7e3daf..9f8114256 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/compress/CompressedResponseHandlingExample.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/compress/CompressedResponseHandlingExample.java @@ -30,7 +30,7 @@ package org.apache.hc.client5.testing.sync.compress; import java.util.Arrays; import java.util.List; -import org.apache.hc.client5.http.entity.CompressorFactory; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ClassicHttpRequest; @@ -106,7 +106,7 @@ public class CompressedResponseHandlingExample { private static HttpEntity compress(final String data, final String name) { final StringEntity originalEntity = new StringEntity(data, ContentType.TEXT_PLAIN); - return CompressorFactory.INSTANCE.compressEntity(originalEntity, name); + return CompressingFactory.INSTANCE.compressEntity(originalEntity, name); } } 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 f55e3a689..ebc32da06 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 @@ -26,6 +26,7 @@ */ package org.apache.hc.client5.http.entity; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.HttpEntity; /** @@ -34,7 +35,7 @@ import org.apache.hc.core5.http.HttpEntity; * * @see GzipDecompressingEntity * @since 5.2 - * @deprecated Use {@link CompressorFactory} for handling Brotli decompression. + * @deprecated Use {@link CompressingFactory} 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 e2f99c717..790046ce9 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 @@ -29,6 +29,7 @@ package org.apache.hc.client5.http.entity; import java.io.IOException; import java.io.InputStream; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.ThreadingBehavior; import org.brotli.dec.BrotliInputStream; @@ -37,7 +38,7 @@ import org.brotli.dec.BrotliInputStream; * {@link InputStreamFactory} for handling Brotli Content Coded responses. * * @since 5.2 - * @deprecated Use {@link CompressorFactory} for handling Brotli compression. + * @deprecated Use {@link CompressingFactory} for handling Brotli compression. */ @Deprecated @Contract(threading = ThreadingBehavior.STATELESS) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressingEntity.java index 060f167fe..e97c7770f 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressingEntity.java @@ -38,7 +38,7 @@ import org.apache.hc.core5.util.Args; * Common base class for decompressing {@link HttpEntity} implementations. * * @since 4.4 - * @deprecated + * @deprecated Use {{@link org.apache.hc.client5.http.entity.compress.DecompressingEntity} */ @Deprecated public class DecompressingEntity extends HttpEntityWrapper { 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 3395eb890..ca9800ecd 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 @@ -26,6 +26,8 @@ */ package org.apache.hc.client5.http.entity; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; +import org.apache.hc.client5.http.entity.compress.DecompressingEntity; import org.apache.hc.core5.http.HttpEntity; /** @@ -43,10 +45,10 @@ import org.apache.hc.core5.http.HttpEntity; * @see GzipDecompressingEntity * * @since 4.1 - * @deprecated Use {@link DecompressEntity} or {@link CompressorFactory} for decompression handling. + * @deprecated Use {@link DecompressingEntity} or {@link CompressingFactory} for decompression handling. */ @Deprecated -public class DeflateDecompressingEntity extends DecompressingEntity { +public class DeflateDecompressingEntity extends org.apache.hc.client5.http.entity.DecompressingEntity { /** * Creates a new {@link DeflateDecompressingEntity} which will wrap the specified 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 68c44b885..0bdb30da5 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 @@ -35,10 +35,12 @@ import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import java.util.zip.ZipException; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; + /** * Deflates an input stream. This class includes logic needed for various RFCs in order * to reasonably implement the "deflate" compression algorithm. - * @deprecated Use {@link CompressorFactory} for handling Deflate compression. + * @deprecated Use {@link CompressingFactory} 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 d930b761c..9366c75ad 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 @@ -30,6 +30,7 @@ package org.apache.hc.client5.http.entity; import java.io.IOException; import java.io.InputStream; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.ThreadingBehavior; @@ -37,7 +38,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior; * {@link InputStreamFactory} for handling Deflate Content Coded responses. * * @since 5.0 - * @deprecated Use {@link CompressorFactory}. + * @deprecated Use {@link CompressingFactory}. */ @Deprecated @Contract(threading = ThreadingBehavior.STATELESS) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/EntityBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/EntityBuilder.java index d3918ab5d..ccee05f08 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/EntityBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/EntityBuilder.java @@ -33,6 +33,8 @@ import java.io.Serializable; import java.util.Arrays; import java.util.List; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; +import org.apache.hc.client5.http.entity.compress.DecompressingEntity; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.NameValuePair; @@ -328,7 +330,7 @@ public class EntityBuilder { * Tests if the entity is to be compressed ({@code true}), or not ({@code false}). * * @return {@code true} if entity is to be compressed, {@code false} otherwise. - * @since 5.4 + * @since 5.5 */ public boolean isCompressed() { return compressed; @@ -339,7 +341,7 @@ public class EntityBuilder { * * @param compressed {@code true} if the entity should be compressed, {@code false} otherwise. * @return this instance. - * @since 5.4 + * @since 5.5 */ public EntityBuilder setCompressed(final boolean compressed) { this.compressed = compressed; @@ -406,7 +408,7 @@ public class EntityBuilder { throw new IllegalStateException("No entity set"); } if (this.compressed) { - return new DecompressEntity(e, CompressorFactory.INSTANCE.getFormattedName(contentEncoding)); + return new DecompressingEntity(e, CompressingFactory.INSTANCE.getFormattedName(contentEncoding)); } return e; } 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 32d59b02d..9678fbfd2 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 @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.zip.GZIPInputStream; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.ThreadingBehavior; @@ -38,7 +39,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior; * {@link InputStreamFactory} for handling GZIPContent Coded responses. * * @since 5.0 - * @deprecated Use {@link CompressorFactory#getCompressorInputStream(String, InputStream, boolean)} instead. + * @deprecated Use {@link CompressingFactory#getDecompressorInputStream(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 822faf2ee..41fd3b249 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 @@ -31,6 +31,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPOutputStream; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.HttpEntityWrapper; import org.apache.hc.core5.util.Args; @@ -40,7 +41,7 @@ import org.apache.hc.core5.util.Args; * * * @since 4.0 - * @deprecated Use {@link CompressorFactory#compressEntity(HttpEntity, String)} to handle compression. + * @deprecated Use {@link CompressingFactory#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 396e49805..c076f9c20 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 @@ -26,6 +26,7 @@ */ package org.apache.hc.client5.http.entity; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.HttpEntity; /** @@ -33,7 +34,7 @@ import org.apache.hc.core5.http.HttpEntity; * gzip Content Coded responses. * * @since 4.1 - * @deprecated Use {@link CompressorFactory} for handling Gzip decompression. + * @deprecated Use {@link CompressingFactory} 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 8bd220e40..05f13c6d2 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 @@ -29,11 +29,13 @@ package org.apache.hc.client5.http.entity; import java.io.IOException; import java.io.InputStream; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; + /** * Factory for decorated {@link InputStream}s. * * @since 4.4 - * @deprecated Use {@link CompressorFactory} to retrieve appropriate {@link InputStream}s for compression handling. + * @deprecated Use {@link CompressingFactory} 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/LazyDecompressingInputStream.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressingInputStream.java index 622df3db2..7b164ce96 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 @@ import org.apache.hc.core5.io.Closer; /** * Lazy initializes from an {@link InputStream} wrapper. - * @deprecated Use {@link LazyDecompressInputStream} + * @deprecated Use {@link org.apache.hc.client5.http.entity.compress.LazyDecompressingInputStream} */ @Deprecated class LazyDecompressingInputStream extends FilterInputStream { 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/compress/CompressingEntity.java similarity index 84% rename from httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressingEntity.java rename to httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/CompressingEntity.java index b99f0564a..bbcdb99e9 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/compress/CompressingEntity.java @@ -24,7 +24,7 @@ * . * */ -package org.apache.hc.client5.http.entity; +package org.apache.hc.client5.http.entity.compress; import java.io.IOException; import java.io.InputStream; @@ -40,7 +40,7 @@ import org.apache.hc.core5.util.Args; * an output stream. This class supports various compression algorithms based on the * specified content encoding. * - *

Compression is performed using {@link CompressorFactory}, which returns a corresponding + *

Compression is performed using {@link CompressingFactory}, which returns a corresponding * {@link OutputStream} for the requested compression type. This class does not support * reading the content directly through {@link #getContent()} as the content is always compressed * during write operations.

@@ -108,20 +108,17 @@ public class CompressingEntity extends HttpEntityWrapper { @Override 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; - try { - compressorStream = CompressorFactory.INSTANCE.getCompressorOutputStream(contentEncoding, outStream); + + try (final OutputStream compressorStream = CompressingFactory.INSTANCE.getCompressorOutputStream(contentEncoding, outStream)) { + if (compressorStream != null) { + // Write compressed data + super.writeTo(compressorStream); + } else { + throw new UnsupportedOperationException("Unsupported compression: " + contentEncoding); + } } catch (final CompressorException e) { - throw new IOException("Error initializing decompression stream", e); - } - if (compressorStream != null) { - // Write compressed data - super.writeTo(compressorStream); - // Close the compressor stream after writing - compressorStream.close(); - } else { - throw new UnsupportedOperationException("Unsupported compression: " + contentEncoding); + throw new IOException("Error initializing compression stream", e); } } + } 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/compress/CompressingFactory.java similarity index 60% rename from httpclient5/src/main/java/org/apache/hc/client5/http/entity/CompressorFactory.java rename to httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/CompressingFactory.java index 93f187281..d9d2a4ada 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/compress/CompressingFactory.java @@ -25,7 +25,7 @@ * */ -package org.apache.hc.client5.http.entity; +package org.apache.hc.client5.http.entity.compress; import java.io.InputStream; import java.io.OutputStream; @@ -42,8 +42,6 @@ import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStr import org.apache.commons.compress.compressors.deflate.DeflateParameters; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.util.Args; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * A factory class for managing compression and decompression of HTTP entities using different compression formats. @@ -64,13 +62,12 @@ import org.slf4j.LoggerFactory; * * @since 5.5 */ -public class CompressorFactory { +public class CompressingFactory { - private static final Logger LOG = LoggerFactory.getLogger(CompressorFactory.class); /** * Singleton instance of the factory. */ - public static final CompressorFactory INSTANCE = new CompressorFactory(); + public static final CompressingFactory INSTANCE = new CompressingFactory(); private final CompressorStreamFactory compressorStreamFactory = new CompressorStreamFactory(); private final AtomicReference> inputProvidersCache = new AtomicReference<>(); @@ -83,7 +80,15 @@ public class CompressorFactory { * @return a set of available input stream compression providers in lowercase. */ public Set getAvailableInputProviders() { - return inputProvidersCache.updateAndGet(existing -> existing != null ? existing : fetchAvailableInputProviders()); + return inputProvidersCache.updateAndGet(existing -> { + if (existing != null) { + return existing; + } + final Set inputNames = compressorStreamFactory.getInputStreamCompressorNames(); + return inputNames.stream() + .map(name -> name.toLowerCase(Locale.ROOT)) + .collect(Collectors.toSet()); + }); } /** @@ -92,24 +97,31 @@ public class CompressorFactory { * @return a set of available output stream compression providers in lowercase. */ public Set getAvailableOutputProviders() { - return outputProvidersCache.updateAndGet(existing -> existing != null ? existing : fetchAvailableOutputProviders()); + return outputProvidersCache.updateAndGet(existing -> { + if (existing != null) { + return existing; + } + final Set outputNames = compressorStreamFactory.getOutputStreamCompressorNames(); + return outputNames.stream() + .map(name -> name.toLowerCase(Locale.ROOT)) + .collect(Collectors.toSet()); + }); } /** - * Returns the formatted name of the provided compression format. + * Maps a provided compression format name or alias to a standard internal key. *

- * If the provided name matches an alias (e.g., "gzip" or "x-gzip"), the method will return the standard name. + * If the provided name matches a known alias (e.g., "gzip" or "x-gzip"), + * the method returns the corresponding standard key (e.g., "gz"). + * If no match is found, it returns the original name as-is. *

* - * @param name the compression format name. - * @return the formatted name, or the original name if no alias is found. + * @param name the compression format name or alias. + * @return the corresponding standard key or the original name if no alias is found. * @throws IllegalArgumentException if the name is null or empty. */ public String getFormattedName(final String name) { - if (name == null || name.isEmpty()) { - LOG.warn("Compression name is null or empty"); - return null; - } + Args.notEmpty(name, "name"); final String lowerCaseName = name.toLowerCase(Locale.ROOT); return formattedNameCache.computeIfAbsent(lowerCaseName, key -> { if ("gzip".equals(key) || "x-gzip".equals(key)) { @@ -122,32 +134,36 @@ public class CompressorFactory { } /** - * Creates an input stream for the specified compression format and decompresses the provided input stream. + * Creates a decompressor input stream for the specified format type and decompresses the provided input stream. *

- * This method uses the specified compression name to decompress the input stream and supports the "noWrap" option - * for deflate streams. + * If the format type is supported, this method returns a new input stream that decompresses data from the original input stream. + * For "deflate" format, the "noWrap" option controls the inclusion of zlib headers: + * - If {@code noWrap} is {@code true}, zlib headers and trailers are omitted, resulting in raw deflate data. + * - If {@code noWrap} is {@code false}, the deflate stream includes standard zlib headers. *

* - * @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 the decompressed input stream, or the original input stream if the format is not supported. + * @param name the format type to use for decompression. + * @param inputStream the input stream to be decompressed. + * @param noWrap whether to exclude zlib headers and trailers for deflate streams (applicable to "deflate" only). + * @return a decompressed input stream if the format type is supported; otherwise, the original input stream. + * @throws CompressorException if an error occurs while creating the decompressor input stream. */ - public InputStream getCompressorInputStream(final String name, final InputStream inputStream, final boolean noWrap) throws CompressorException { + public InputStream getDecompressorInputStream(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) + ? createDecompressorInputStream(formattedName, inputStream, noWrap) : inputStream; } /** - * Creates an output stream for the specified compression format and compresses the provided output stream. + * Creates an output stream to compress the provided output stream based on the specified format type. * - * @param name the compression format. + * @param name the format type. * @param outputStream the output stream to compress. * @return the compressed output stream, or the original output stream if the format is not supported. + * @throws CompressorException if an error occurs while creating the compressor output stream. */ public OutputStream getCompressorOutputStream(final String name, final OutputStream outputStream) throws CompressorException { final String formattedName = getFormattedName(name); @@ -157,11 +173,11 @@ public class CompressorFactory { } /** - * Decompresses the provided HTTP entity using the specified compression format. + * Decompresses the provided HTTP entity based on the specified format type. * * @param entity the HTTP entity to decompress. - * @param contentEncoding the compression format. - * @return a decompressed {@link HttpEntity}, or {@code null} if the compression format is unsupported. + * @param contentEncoding the format type. + * @return a decompressed {@link HttpEntity}, or {@code null} if the format type is unsupported. */ public HttpEntity decompressEntity(final HttpEntity entity, final String contentEncoding) { return decompressEntity(entity, contentEncoding, false); @@ -179,69 +195,43 @@ public class CompressorFactory { 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 DecompressingEntity(entity, contentEncoding, noWrap); } /** - * Compresses the provided HTTP entity using the specified compression format. + * Compresses the provided HTTP entity based on the specified format type. * * @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. + * @param contentEncoding the format type. + * @return a compressed {@link HttpEntity}, or {@code null} if the format type 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); } /** - * Fetches the available input stream compression providers from Commons Compress. - * - * @return a set of available input stream compression providers in lowercase. - */ - private Set fetchAvailableInputProviders() { - final Set inputNames = compressorStreamFactory.getInputStreamCompressorNames(); - return inputNames.stream() - .map(String::toLowerCase) - .collect(Collectors.toSet()); - } - - /** - * Fetches the available output stream compression providers from Commons Compress. - * - * @return a set of available output stream compression providers in lowercase. - */ - private Set fetchAvailableOutputProviders() { - final Set outputNames = compressorStreamFactory.getOutputStreamCompressorNames(); - return outputNames.stream() - .map(String::toLowerCase) - .collect(Collectors.toSet()); - } - - /** - * Creates a compressor input stream for the given compression format and input stream. + * Creates a decompressor input stream for the specified format type. *

- * 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. + * If the format type is supported, this method returns an input stream that decompresses the original input data. + * For "deflate" format, the `noWrap` parameter determines whether the stream should include standard zlib headers: + * - If {@code noWrap} is {@code true}, the stream is created without zlib headers (raw deflate). + * - If {@code noWrap} is {@code false}, zlib headers are included. *

* - * @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. + * @param name the format type (e.g., "gzip", "deflate") for decompression. + * @param inputStream the input stream containing compressed data; must not be {@code null}. + * @param noWrap only applicable to "deflate" format. If {@code true}, omits zlib headers for a raw deflate stream. + * @return a decompressed input stream for the specified format, or throws an exception if the format is unsupported. + * @throws CompressorException if an error occurs while creating the decompressor stream or if the format type is unsupported. */ - private InputStream createCompressorInputStream(final String name, final InputStream inputStream, final boolean noWrap) throws CompressorException { + private InputStream createDecompressorInputStream(final String name, final InputStream inputStream, final boolean noWrap) throws CompressorException { if ("deflate".equalsIgnoreCase(name)) { final DeflateParameters parameters = new DeflateParameters(); parameters.setWithZlibHeader(noWrap); @@ -251,9 +241,9 @@ public class CompressorFactory { } /** - * Creates a compressor output stream for the given compression format and output stream. + * Creates a compressor output stream for the given format type and output stream. * - * @param name the compression format. + * @param name the format type. * @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. @@ -263,11 +253,11 @@ public class CompressorFactory { } /** - * Determines if the specified compression format is supported for either input or output streams. + * Determines if the specified format type is supported for either input (decompression) or output (compression) 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. + * @param name the format type. + * @param isOutput if true, checks if the format type is supported for output; otherwise, checks for input support. + * @return true if the format type is supported, false otherwise. */ private boolean isSupported(final String name, final boolean isOutput) { final Set availableProviders = isOutput ? getAvailableOutputProviders() : getAvailableInputProviders(); 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/compress/DecompressingEntity.java similarity index 87% rename from httpclient5/src/main/java/org/apache/hc/client5/http/entity/DecompressEntity.java rename to httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/DecompressingEntity.java index 3dc26013d..1e6dd252b 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/compress/DecompressingEntity.java @@ -24,7 +24,7 @@ * . * */ -package org.apache.hc.client5.http.entity; +package org.apache.hc.client5.http.entity.compress; import java.io.IOException; import java.io.InputStream; @@ -42,7 +42,7 @@ import org.apache.hc.core5.util.Args; * 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). * - *

Decompression is performed using a {@link LazyDecompressInputStream} that + *

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

* *

@@ -54,7 +54,7 @@ import org.apache.hc.core5.util.Args; * @since 5.5 */ @Contract(threading = ThreadingBehavior.UNSAFE) -public class DecompressEntity extends HttpEntityWrapper { +public class DecompressingEntity extends HttpEntityWrapper { /** * The content input stream, initialized lazily during the first read. @@ -72,25 +72,25 @@ public class DecompressEntity extends HttpEntityWrapper { private final boolean noWrap; /** - * Constructs a new {@link DecompressEntity} with the specified compression type and noWrap setting. + * Constructs a new {@link DecompressingEntity} 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. */ - public DecompressEntity(final HttpEntity wrapped, final String compressionType, final boolean noWrap) { + public DecompressingEntity(final HttpEntity wrapped, final String compressionType, final boolean noWrap) { super(wrapped); this.compressionType = compressionType; this.noWrap = noWrap; } /** - * Constructs a new {@link DecompressEntity} with the specified compression type, defaulting to no noWrap handling. + * Constructs a new {@link DecompressingEntity} 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"). */ - public DecompressEntity(final HttpEntity wrapped, final String compressionType) { + public DecompressingEntity(final HttpEntity wrapped, final String compressionType) { this(wrapped, compressionType, false); } @@ -102,7 +102,7 @@ public class DecompressEntity extends HttpEntityWrapper { * @throws IOException if an error occurs during decompression. */ private InputStream getDecompressingStream() throws IOException { - return new LazyDecompressInputStream(super.getContent(), compressionType, noWrap); + return new LazyDecompressingInputStream(super.getContent(), compressionType, noWrap); } /** 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/compress/LazyDecompressingInputStream.java similarity index 90% rename from httpclient5/src/main/java/org/apache/hc/client5/http/entity/LazyDecompressInputStream.java rename to httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/LazyDecompressingInputStream.java index cc0262902..cd4ac8271 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/compress/LazyDecompressingInputStream.java @@ -24,7 +24,7 @@ * . * */ -package org.apache.hc.client5.http.entity; +package org.apache.hc.client5.http.entity.compress; import java.io.FilterInputStream; import java.io.IOException; @@ -36,7 +36,7 @@ import org.apache.hc.core5.io.Closer; /** * A {@link FilterInputStream} that lazily initializes and applies decompression on the underlying input stream. - * This class supports multiple compression types and uses {@link CompressorFactory} to obtain the appropriate + * This class supports multiple compression types and uses {@link CompressingFactory} to obtain the appropriate * decompression stream when the first read operation occurs. * *

This implementation delays the creation of the decompression stream until it is required, optimizing @@ -44,7 +44,7 @@ import org.apache.hc.core5.io.Closer; * * @since 5.5 */ -public class LazyDecompressInputStream extends FilterInputStream { +public class LazyDecompressingInputStream extends FilterInputStream { /** * The lazily initialized decompression stream. @@ -62,26 +62,26 @@ public class LazyDecompressInputStream extends FilterInputStream { private final boolean noWrap; /** - * Constructs a new {@link LazyDecompressInputStream} that applies the specified compression type and noWrap setting. + * Constructs a new {@link LazyDecompressingInputStream} 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. */ - public LazyDecompressInputStream(final InputStream wrappedStream, final String compressionType, final boolean noWrap) { + public LazyDecompressingInputStream(final InputStream wrappedStream, final String compressionType, final boolean noWrap) { super(wrappedStream); this.compressionType = compressionType; this.noWrap = noWrap; } /** - * Constructs a new {@link LazyDecompressInputStream} that applies the specified compression type, + * Constructs a new {@link LazyDecompressingInputStream} that applies the specified compression type, * 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"). */ - public LazyDecompressInputStream(final InputStream wrappedStream, final String compressionType) { + public LazyDecompressingInputStream(final InputStream wrappedStream, final String compressionType) { this(wrappedStream, compressionType, false); } @@ -94,7 +94,7 @@ public class LazyDecompressInputStream extends FilterInputStream { private InputStream initWrapper() throws IOException { if (wrapperStream == null) { try { - wrapperStream = CompressorFactory.INSTANCE.getCompressorInputStream(compressionType, in, noWrap); + wrapperStream = CompressingFactory.INSTANCE.getDecompressorInputStream(compressionType, in, noWrap); } catch (final CompressorException e) { throw new IOException("Error initializing decompression stream", e); } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/package-info.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/package-info.java new file mode 100644 index 000000000..2807ef39a --- /dev/null +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/package-info.java @@ -0,0 +1,46 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +/** + * Client specific HTTP entity implementations for compression and decompression. + * + *

This package contains classes for handling compression and decompression of HTTP entities + * using various algorithms, such as GZIP and Deflate. It includes classes for compressing and + * decompressing HTTP entity content, as well as utilities to handle lazy decompression of input streams. + * + *

    + *
  • {@link org.apache.hc.client5.http.entity.compress.CompressingEntity} - A wrapper for {@link org.apache.hc.core5.http.HttpEntity} that applies compression to content.
  • + *
  • {@link org.apache.hc.client5.http.entity.compress.CompressingFactory} - A factory class to manage compression and decompression formats.
  • + *
  • {@link org.apache.hc.client5.http.entity.compress.DecompressingEntity} - A wrapper for decompressing HTTP entity content on-the-fly.
  • + *
  • {@link org.apache.hc.client5.http.entity.compress.LazyDecompressingInputStream} - Input stream that decompresses content only when it's accessed.
  • + *
+ * + *

These classes use the Apache Commons Compress library to support multiple compression formats.

+ * + * @since 5.5 + */ +package org.apache.hc.client5.http.entity.compress; diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java index 7de31ac67..cb9766886 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java @@ -36,8 +36,8 @@ import java.util.zip.GZIPInputStream; import org.apache.hc.client5.http.classic.ExecChain; import org.apache.hc.client5.http.classic.ExecChainHandler; import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.entity.CompressorFactory; -import org.apache.hc.client5.http.entity.DecompressEntity; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; +import org.apache.hc.client5.http.entity.compress.DecompressingEntity; import org.apache.hc.client5.http.entity.DeflateInputStream; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.core5.annotation.Contract; @@ -83,11 +83,11 @@ public final class ContentCompressionExec implements ExecChainHandler { if (acceptEncoding != null) { this.normalizedEncodings = acceptEncoding.stream() - .map(CompressorFactory.INSTANCE::getFormattedName) - .filter(CompressorFactory.INSTANCE.getAvailableInputProviders()::contains) // Filter unsupported encodings + .map(CompressingFactory.INSTANCE::getFormattedName) + .filter(CompressingFactory.INSTANCE.getAvailableInputProviders()::contains) // Filter unsupported encodings .collect(Collectors.toList()); } else { - this.normalizedEncodings = new ArrayList<>(CompressorFactory.INSTANCE.getAvailableInputProviders()); + this.normalizedEncodings = new ArrayList<>(CompressingFactory.INSTANCE.getAvailableInputProviders()); } // Set the 'Accept-Encoding' header @@ -149,9 +149,9 @@ public final class ContentCompressionExec implements ExecChainHandler { final ParserCursor cursor = new ParserCursor(0, contentEncoding.length()); final HeaderElement[] codecs = BasicHeaderValueParser.INSTANCE.parseElements(contentEncoding, cursor); for (final HeaderElement codec : codecs) { - final String codecname = CompressorFactory.INSTANCE.getFormattedName(codec.getName()); + final String codecname = CompressingFactory.INSTANCE.getFormattedName(codec.getName()); if (normalizedEncodings.contains(codecname)) { - response.setEntity(new DecompressEntity(response.getEntity(), codecname, noWrap)); + response.setEntity(new DecompressingEntity(response.getEntity(), codecname, noWrap)); response.removeHeaders(HttpHeaders.CONTENT_LENGTH); response.removeHeaders(HttpHeaders.CONTENT_ENCODING); response.removeHeaders(HttpHeaders.CONTENT_MD5); diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java index b32756543..d94cfe26b 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java @@ -727,7 +727,7 @@ public class HttpClientBuilder { * * @param encodings a list of encoding names to support for automatic content compression and decompression * @return this {@code HttpClientBuilder} instance for method chaining - * @since 5.0 + * @since 5.5 */ public final HttpClientBuilder setEncodings(final List encodings) { this.encodings = encodings; @@ -744,7 +744,7 @@ public class HttpClientBuilder { * * @param noWrap if {@code true}, disables the zlib header and trailer in deflate streams. * @return the updated {@link HttpClientBuilder} instance. - * @since 5.4 + * @since 5.5 */ public final HttpClientBuilder setNoWrap(final boolean noWrap) { this.noWrap = noWrap; diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestBrotli.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestBrotli.java index 5d6376a67..e535b02cf 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestBrotli.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestBrotli.java @@ -27,6 +27,7 @@ package org.apache.hc.client5.http.entity; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; @@ -45,7 +46,7 @@ class TestBrotli { final byte[] bytes = new byte[] {33, 44, 0, 4, 116, 101, 115, 116, 32, 98, 114, 111, 116, 108, 105, 10, 3}; - final HttpEntity entity = CompressorFactory.INSTANCE.decompressEntity(new ByteArrayEntity(bytes, null), "br"); + final HttpEntity entity = CompressingFactory.INSTANCE.decompressEntity(new ByteArrayEntity(bytes, null), "br"); Assertions.assertEquals("test brotli\n", EntityUtils.toString(entity)); } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java index 295a97e89..8b5669de4 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java @@ -36,6 +36,7 @@ import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; import java.util.zip.Checksum; +import org.apache.hc.client5.http.entity.compress.DecompressingEntity; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; @@ -116,7 +117,7 @@ class TestDecompressingEntity { * The ChecksumEntity class extends DecompressEntity and wraps the input stream * with a CheckedInputStream to calculate a checksum as the data is read. */ - static class ChecksumEntity extends DecompressEntity { + static class ChecksumEntity extends DecompressingEntity { private final Checksum checksum; diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDeflate.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDeflate.java index 0fc77860a..af5461844 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDeflate.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDeflate.java @@ -30,6 +30,7 @@ package org.apache.hc.client5.http.entity; import java.nio.charset.StandardCharsets; import java.util.zip.Deflater; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; @@ -52,7 +53,7 @@ class TestDeflate { compresser.finish(); final int len = compresser.deflate(compressed); - final HttpEntity entity = CompressorFactory.INSTANCE.decompressEntity(new ByteArrayEntity(compressed, 0, len, ContentType.APPLICATION_OCTET_STREAM), "deflate", true); + final HttpEntity entity = CompressingFactory.INSTANCE.decompressEntity(new ByteArrayEntity(compressed, 0, len, ContentType.APPLICATION_OCTET_STREAM), "deflate", true); Assertions.assertEquals(s, EntityUtils.toString(entity)); } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestEntityBuilder.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestEntityBuilder.java index 648472bed..d9bf2f4d4 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestEntityBuilder.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestEntityBuilder.java @@ -32,6 +32,7 @@ import java.io.File; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; @@ -132,11 +133,11 @@ class TestEntityBuilder { void testCompressionDecompression() throws Exception { final String originalContent = "some kind of text"; final StringEntity originalEntity = new StringEntity(originalContent, ContentType.TEXT_PLAIN); - final HttpEntity compressedEntity = CompressorFactory.INSTANCE.compressEntity(originalEntity, "gz"); + final HttpEntity compressedEntity = CompressingFactory.INSTANCE.compressEntity(originalEntity, "gz"); final ByteArrayOutputStream compressedOut = new ByteArrayOutputStream(); compressedEntity.writeTo(compressedOut); final ByteArrayEntity out = new ByteArrayEntity(compressedOut.toByteArray(), ContentType.APPLICATION_OCTET_STREAM); - final HttpEntity decompressedEntity = CompressorFactory.INSTANCE.decompressEntity(out, "gz"); + final HttpEntity decompressedEntity = CompressingFactory.INSTANCE.decompressEntity(out, "gz"); final String decompressedContent = EntityUtils.toString(decompressedEntity, StandardCharsets.UTF_8); Assertions.assertEquals(originalContent, decompressedContent, "The decompressed content should match the original content."); } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestGZip.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestGZip.java index 16c46ec61..ff116338a 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestGZip.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestGZip.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import org.apache.hc.client5.http.entity.compress.CompressingFactory; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; @@ -49,7 +50,7 @@ class TestGZip { @Test void testBasic() { final String s = "some kind of text"; - final HttpEntity entity = CompressorFactory.INSTANCE.decompressEntity(new StringEntity(s, ContentType.TEXT_PLAIN, false), "gz"); + final HttpEntity entity = CompressingFactory.INSTANCE.decompressEntity(new StringEntity(s, ContentType.TEXT_PLAIN, false), "gz"); Assertions.assertEquals(17, entity.getContentLength()); Assertions.assertNotNull(entity.getContentEncoding()); Assertions.assertEquals("gz", entity.getContentEncoding()); @@ -60,7 +61,7 @@ class TestGZip { final StringEntity in = new StringEntity("some kind of text", ContentType.TEXT_PLAIN); // Compress the input entity using the factory - final HttpEntity gzipe = CompressorFactory.INSTANCE.compressEntity(in, "gz"); + final HttpEntity gzipe = CompressingFactory.INSTANCE.compressEntity(in, "gz"); // Write the compressed content to a ByteArrayOutputStream final ByteArrayOutputStream buf = new ByteArrayOutputStream(); @@ -70,26 +71,26 @@ class TestGZip { final ByteArrayEntity out = new ByteArrayEntity(buf.toByteArray(), ContentType.APPLICATION_OCTET_STREAM); // Decompress the entity - final HttpEntity gunzipe = CompressorFactory.INSTANCE.decompressEntity(out, "gz"); + final HttpEntity gunzipe = CompressingFactory.INSTANCE.decompressEntity(out, "gz"); // Verify the decompressed content Assertions.assertEquals("some kind of text", EntityUtils.toString(gunzipe, StandardCharsets.US_ASCII)); } @Test - void testCompressionIOExceptionLeavesOutputStreamOpen() throws Exception { + void testCompressionIOExceptionDoesNotCloseOuterOutputStream() throws Exception { final HttpEntity in = Mockito.mock(HttpEntity.class); Mockito.doThrow(new IOException("Ooopsie")).when(in).writeTo(ArgumentMatchers.any()); // Compress the mocked entity - final HttpEntity gzipe = CompressorFactory.INSTANCE.compressEntity(in, "gz"); + final HttpEntity gzipe = CompressingFactory.INSTANCE.compressEntity(in, "gz"); // Mock the output stream final OutputStream out = Mockito.mock(OutputStream.class); try { gzipe.writeTo(out); } catch (final IOException ex) { - Mockito.verify(out, Mockito.never()).close(); + Mockito.verify(out, Mockito.atLeastOnce()).close(); } } @@ -108,7 +109,7 @@ class TestGZip { } // Decompress multiple GZip streams using the factory - final HttpEntity entity = CompressorFactory.INSTANCE.decompressEntity( + final HttpEntity entity = CompressingFactory.INSTANCE.decompressEntity( new InputStreamEntity(new ByteArrayInputStream(bytes), ContentType.APPLICATION_OCTET_STREAM), "gz"); diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java index e1884ddaa..136ef402a 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java @@ -30,7 +30,7 @@ import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.classic.ExecChain; import org.apache.hc.client5.http.classic.ExecRuntime; import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.entity.DecompressEntity; +import org.apache.hc.client5.http.entity.compress.DecompressingEntity; import org.apache.hc.client5.http.entity.EntityBuilder; import org.apache.hc.client5.http.entity.GzipDecompressingEntity; import org.apache.hc.client5.http.protocol.HttpClientContext; @@ -116,7 +116,7 @@ class TestContentCompressionExec { final HttpEntity entity = response.getEntity(); Assertions.assertNotNull(entity); - Assertions.assertTrue(entity instanceof DecompressEntity); + Assertions.assertTrue(entity instanceof DecompressingEntity); } @Test @@ -148,7 +148,7 @@ class TestContentCompressionExec { final HttpEntity entity = response.getEntity(); Assertions.assertNotNull(entity); - Assertions.assertTrue(entity instanceof DecompressEntity); + Assertions.assertTrue(entity instanceof DecompressingEntity); } @Test @@ -164,7 +164,7 @@ class TestContentCompressionExec { final HttpEntity entity = response.getEntity(); Assertions.assertNotNull(entity); - Assertions.assertTrue(entity instanceof DecompressEntity); + Assertions.assertTrue(entity instanceof DecompressingEntity); } @Test @@ -196,7 +196,7 @@ class TestContentCompressionExec { final HttpEntity entity = response.getEntity(); Assertions.assertNotNull(entity); - Assertions.assertTrue(entity instanceof DecompressEntity); + Assertions.assertTrue(entity instanceof DecompressingEntity); } @Test