diff --git a/client/src/main/java/org/asynchttpclient/AsyncCompletionHandler.java b/client/src/main/java/org/asynchttpclient/AsyncCompletionHandler.java index fe193d37f..e5cb67207 100644 --- a/client/src/main/java/org/asynchttpclient/AsyncCompletionHandler.java +++ b/client/src/main/java/org/asynchttpclient/AsyncCompletionHandler.java @@ -18,6 +18,7 @@ import io.netty.handler.codec.http.HttpHeaders; import org.asynchttpclient.handler.ProgressAsyncHandler; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,7 +67,7 @@ public State onTrailingHeadersReceived(HttpHeaders headers) throws Exception { } @Override - public final T onCompleted() throws Exception { + public final @Nullable T onCompleted() throws Exception { return onCompleted(builder.build()); } @@ -83,7 +84,7 @@ public void onThrowable(Throwable t) { * {@link Future} * @throws Exception if something wrong happens */ - public abstract T onCompleted(Response response) throws Exception; + public abstract @Nullable T onCompleted(@Nullable Response response) throws Exception; /** * Invoked when the HTTP headers have been fully written on the I/O socket. diff --git a/client/src/main/java/org/asynchttpclient/AsyncCompletionHandlerBase.java b/client/src/main/java/org/asynchttpclient/AsyncCompletionHandlerBase.java index 3498bd643..8ad58eff6 100644 --- a/client/src/main/java/org/asynchttpclient/AsyncCompletionHandlerBase.java +++ b/client/src/main/java/org/asynchttpclient/AsyncCompletionHandlerBase.java @@ -17,12 +17,14 @@ package org.asynchttpclient; +import org.jetbrains.annotations.Nullable; + /** * Simple {@link AsyncHandler} of type {@link Response} */ public class AsyncCompletionHandlerBase extends AsyncCompletionHandler { @Override - public Response onCompleted(Response response) throws Exception { + public @Nullable Response onCompleted(@Nullable Response response) throws Exception { return response; } } diff --git a/client/src/main/java/org/asynchttpclient/AsyncHandler.java b/client/src/main/java/org/asynchttpclient/AsyncHandler.java index 80a1fc191..74099cc4d 100644 --- a/client/src/main/java/org/asynchttpclient/AsyncHandler.java +++ b/client/src/main/java/org/asynchttpclient/AsyncHandler.java @@ -18,6 +18,7 @@ import io.netty.channel.Channel; import io.netty.handler.codec.http.HttpHeaders; import org.asynchttpclient.netty.request.NettyRequest; +import org.jetbrains.annotations.Nullable; import javax.net.ssl.SSLSession; import java.net.InetSocketAddress; @@ -115,7 +116,7 @@ default State onTrailingHeadersReceived(HttpHeaders headers) throws Exception { * @return T Value that will be returned by the associated {@link Future} * @throws Exception if something wrong happens */ - T onCompleted() throws Exception; + @Nullable T onCompleted() throws Exception; /** * Notify the callback before hostname resolution diff --git a/client/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java b/client/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java index 1c5ab1b5a..972fa0b3a 100644 --- a/client/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java +++ b/client/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java @@ -34,6 +34,7 @@ import org.asynchttpclient.netty.channel.ConnectionSemaphoreFactory; import org.asynchttpclient.proxy.ProxyServer; import org.asynchttpclient.proxy.ProxyServerSelector; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.time.Duration; @@ -159,7 +160,7 @@ public interface AsyncHttpClientConfig { * @return the {@link ThreadFactory} an {@link AsyncHttpClient} use for handling asynchronous response. If no {@link ThreadFactory} has been explicitly * provided, this method will return {@code null} */ - ThreadFactory getThreadFactory(); + @Nullable ThreadFactory getThreadFactory(); /** * An instance of {@link ProxyServer} used by an {@link AsyncHttpClient} @@ -173,14 +174,14 @@ public interface AsyncHttpClientConfig { * * @return an instance of {@link SslContext} used for SSL connection. */ - SslContext getSslContext(); + @Nullable SslContext getSslContext(); /** * Return the current {@link Realm} * * @return the current {@link Realm} */ - Realm getRealm(); + @Nullable Realm getRealm(); /** * Return the list of {@link RequestFilter} @@ -259,12 +260,12 @@ public interface AsyncHttpClientConfig { /** * @return the array of enabled protocols */ - String[] getEnabledProtocols(); + @Nullable String[] getEnabledProtocols(); /** * @return the array of enabled cipher suites */ - String[] getEnabledCipherSuites(); + @Nullable String[] getEnabledCipherSuites(); /** * @return if insecure cipher suites must be filtered out (only used when not explicitly passing enabled cipher suites) @@ -293,7 +294,7 @@ public interface AsyncHttpClientConfig { int getHandshakeTimeout(); - SslEngineFactory getSslEngineFactory(); + @Nullable SslEngineFactory getSslEngineFactory(); int getChunkedFileChunkSize(); @@ -309,23 +310,23 @@ public interface AsyncHttpClientConfig { Map, Object> getChannelOptions(); - EventLoopGroup getEventLoopGroup(); + @Nullable EventLoopGroup getEventLoopGroup(); boolean isUseNativeTransport(); boolean isUseOnlyEpollNativeTransport(); - Consumer getHttpAdditionalChannelInitializer(); + @Nullable Consumer getHttpAdditionalChannelInitializer(); - Consumer getWsAdditionalChannelInitializer(); + @Nullable Consumer getWsAdditionalChannelInitializer(); ResponseBodyPartFactory getResponseBodyPartFactory(); - ChannelPool getChannelPool(); + @Nullable ChannelPool getChannelPool(); - ConnectionSemaphoreFactory getConnectionSemaphoreFactory(); + @Nullable ConnectionSemaphoreFactory getConnectionSemaphoreFactory(); - Timer getNettyTimer(); + @Nullable Timer getNettyTimer(); /** * @return the duration between tick of {@link HashedWheelTimer} @@ -357,7 +358,7 @@ public interface AsyncHttpClientConfig { int getSoRcvBuf(); - ByteBufAllocator getAllocator(); + @Nullable ByteBufAllocator getAllocator(); int getIoThreadsCount(); diff --git a/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClient.java b/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClient.java index efcab12a9..ab841fa28 100644 --- a/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClient.java +++ b/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClient.java @@ -30,6 +30,7 @@ import org.asynchttpclient.handler.resumable.ResumableAsyncHandler; import org.asynchttpclient.netty.channel.ChannelManager; import org.asynchttpclient.netty.request.NettyRequestSender; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,7 +69,7 @@ public class DefaultAsyncHttpClient implements AsyncHttpClient { * Default signature calculator to use for all requests constructed by this * client instance. */ - private SignatureCalculator signatureCalculator; + private @Nullable SignatureCalculator signatureCalculator; /** * Create a new HTTP Asynchronous Client using the default @@ -95,8 +96,14 @@ public DefaultAsyncHttpClient(AsyncHttpClientConfig config) { this.config = config; noRequestFilters = config.getRequestFilters().isEmpty(); - allowStopNettyTimer = config.getNettyTimer() == null; - nettyTimer = allowStopNettyTimer ? newNettyTimer(config) : config.getNettyTimer(); + final Timer configTimer = config.getNettyTimer(); + if (configTimer == null) { + allowStopNettyTimer = true; + nettyTimer = newNettyTimer(config); + } else { + allowStopNettyTimer = false; + nettyTimer = configTimer; + } channelManager = new ChannelManager(config, nettyTimer); requestSender = new NettyRequestSender(config, channelManager, nettyTimer, new AsyncHttpClientState(closed)); diff --git a/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClientConfig.java b/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClientConfig.java index 9dfaa89f4..059cc3e78 100644 --- a/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClientConfig.java +++ b/client/src/main/java/org/asynchttpclient/DefaultAsyncHttpClientConfig.java @@ -34,6 +34,7 @@ import org.asynchttpclient.proxy.ProxyServer; import org.asynchttpclient.proxy.ProxyServerSelector; import org.asynchttpclient.util.ProxyUtils; +import org.jetbrains.annotations.Nullable; import java.time.Duration; import java.util.Collections; @@ -44,7 +45,63 @@ import java.util.concurrent.ThreadFactory; import java.util.function.Consumer; -import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.*; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultAcquireFreeChannelTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultAggregateWebSocketFrameFragments; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultChunkedFileChunkSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultCompressionEnforced; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultConnectTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultConnectionPoolCleanerPeriod; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultConnectionTtl; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultDisableHttpsEndpointIdentificationAlgorithm; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultDisableUrlEncodingForBoundRequests; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultDisableZeroCopy; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnableAutomaticDecompression; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnableWebSocketCompression; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnabledCipherSuites; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnabledProtocols; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultExpiredCookieEvictionDelay; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultFilterInsecureCipherSuites; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultFollowRedirect; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHandshakeTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHashedWheelTimerSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHashedWheelTimerTickDuration; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecInitialBufferSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecMaxChunkSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecMaxHeaderSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultHttpClientCodecMaxInitialLineLength; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultIoThreadsCount; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultKeepAlive; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultKeepEncodingHeader; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxConnections; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxConnectionsPerHost; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxRedirects; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxRequestRetry; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultPooledConnectionIdleTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultReadTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultRequestTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultShutdownQuietPeriod; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultShutdownTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoKeepAlive; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoLinger; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoRcvBuf; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoReuseAddress; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSoSndBuf; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSslSessionCacheSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultSslSessionTimeout; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultStrict302Handling; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultTcpNoDelay; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultThreadPoolName; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseInsecureTrustManager; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseLaxCookieEncoder; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseNativeTransport; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseOnlyEpollNativeTransport; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseOpenSsl; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseProxyProperties; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUseProxySelector; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultUserAgent; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultValidateResponseHeaders; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultWebSocketMaxBufferSize; +import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultWebSocketMaxFrameSize; /** * Configuration class to use with a {@link AsyncHttpClient}. System property can be also used to configure this object default behavior by doing:
@@ -62,7 +119,7 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig { private final boolean enableAutomaticDecompression; private final String userAgent; - private final Realm realm; + private final @Nullable Realm realm; private final int maxRequestRetry; private final boolean disableUrlEncodingForBoundRequests; private final boolean useLaxCookieEncoder; @@ -92,8 +149,8 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig { private final int maxConnections; private final int maxConnectionsPerHost; private final int acquireFreeChannelTimeout; - private final ChannelPool channelPool; - private final ConnectionSemaphoreFactory connectionSemaphoreFactory; + private final @Nullable ChannelPool channelPool; + private final @Nullable ConnectionSemaphoreFactory connectionSemaphoreFactory; private final KeepAliveStrategy keepAliveStrategy; // ssl @@ -101,13 +158,13 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig { private final boolean useInsecureTrustManager; private final boolean disableHttpsEndpointIdentificationAlgorithm; private final int handshakeTimeout; - private final String[] enabledProtocols; - private final String[] enabledCipherSuites; + private final @Nullable String[] enabledProtocols; + private final @Nullable String[] enabledCipherSuites; private final boolean filterInsecureCipherSuites; private final int sslSessionCacheSize; private final int sslSessionTimeout; - private final SslContext sslContext; - private final SslEngineFactory sslEngineFactory; + private final @Nullable SslContext sslContext; + private final @Nullable SslEngineFactory sslEngineFactory; // filters private final List requestFilters; @@ -126,20 +183,20 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig { private final int httpClientCodecInitialBufferSize; private final int chunkedFileChunkSize; private final Map, Object> channelOptions; - private final EventLoopGroup eventLoopGroup; + private final @Nullable EventLoopGroup eventLoopGroup; private final boolean useNativeTransport; private final boolean useOnlyEpollNativeTransport; - private final ByteBufAllocator allocator; + private final @Nullable ByteBufAllocator allocator; private final boolean tcpNoDelay; private final boolean soReuseAddress; private final boolean soKeepAlive; private final int soLinger; private final int soSndBuf; private final int soRcvBuf; - private final Timer nettyTimer; - private final ThreadFactory threadFactory; - private final Consumer httpAdditionalChannelInitializer; - private final Consumer wsAdditionalChannelInitializer; + private final @Nullable Timer nettyTimer; + private final @Nullable ThreadFactory threadFactory; + private final @Nullable Consumer httpAdditionalChannelInitializer; + private final @Nullable Consumer wsAdditionalChannelInitializer; private final ResponseBodyPartFactory responseBodyPartFactory; private final int ioThreadsCount; private final long hashedWheelTimerTickDuration; @@ -152,7 +209,7 @@ private DefaultAsyncHttpClientConfig(// http boolean compressionEnforced, boolean enableAutomaticDecompression, String userAgent, - Realm realm, + @Nullable Realm realm, int maxRequestRetry, boolean disableUrlEncodingForBoundRequests, boolean useLaxCookieEncoder, @@ -178,8 +235,8 @@ private DefaultAsyncHttpClientConfig(// http int maxConnections, int maxConnectionsPerHost, int acquireFreeChannelTimeout, - ChannelPool channelPool, - ConnectionSemaphoreFactory connectionSemaphoreFactory, + @Nullable ChannelPool channelPool, + @Nullable ConnectionSemaphoreFactory connectionSemaphoreFactory, KeepAliveStrategy keepAliveStrategy, // ssl @@ -187,13 +244,13 @@ private DefaultAsyncHttpClientConfig(// http boolean useInsecureTrustManager, boolean disableHttpsEndpointIdentificationAlgorithm, int handshakeTimeout, - String[] enabledProtocols, - String[] enabledCipherSuites, + @Nullable String[] enabledProtocols, + @Nullable String[] enabledCipherSuites, boolean filterInsecureCipherSuites, int sslSessionCacheSize, int sslSessionTimeout, - SslContext sslContext, - SslEngineFactory sslEngineFactory, + @Nullable SslContext sslContext, + @Nullable SslEngineFactory sslEngineFactory, // filters List requestFilters, @@ -222,14 +279,14 @@ private DefaultAsyncHttpClientConfig(// http int webSocketMaxBufferSize, int webSocketMaxFrameSize, Map, Object> channelOptions, - EventLoopGroup eventLoopGroup, + @Nullable EventLoopGroup eventLoopGroup, boolean useNativeTransport, boolean useOnlyEpollNativeTransport, - ByteBufAllocator allocator, - Timer nettyTimer, - ThreadFactory threadFactory, - Consumer httpAdditionalChannelInitializer, - Consumer wsAdditionalChannelInitializer, + @Nullable ByteBufAllocator allocator, + @Nullable Timer nettyTimer, + @Nullable ThreadFactory threadFactory, + @Nullable Consumer httpAdditionalChannelInitializer, + @Nullable Consumer wsAdditionalChannelInitializer, ResponseBodyPartFactory responseBodyPartFactory, int ioThreadsCount, long hashedWheelTimerTickDuration, @@ -370,7 +427,7 @@ public String getUserAgent() { } @Override - public Realm getRealm() { + public @Nullable Realm getRealm() { return realm; } @@ -488,12 +545,12 @@ public int getAcquireFreeChannelTimeout() { } @Override - public ChannelPool getChannelPool() { + public @Nullable ChannelPool getChannelPool() { return channelPool; } @Override - public ConnectionSemaphoreFactory getConnectionSemaphoreFactory() { + public @Nullable ConnectionSemaphoreFactory getConnectionSemaphoreFactory() { return connectionSemaphoreFactory; } @@ -529,12 +586,12 @@ public int getHandshakeTimeout() { } @Override - public String[] getEnabledProtocols() { + public @Nullable String[] getEnabledProtocols() { return enabledProtocols; } @Override - public String[] getEnabledCipherSuites() { + public @Nullable String[] getEnabledCipherSuites() { return enabledCipherSuites; } @@ -554,12 +611,12 @@ public int getSslSessionTimeout() { } @Override - public SslContext getSslContext() { + public @Nullable SslContext getSslContext() { return sslContext; } @Override - public SslEngineFactory getSslEngineFactory() { + public @Nullable SslEngineFactory getSslEngineFactory() { return sslEngineFactory; } @@ -658,7 +715,7 @@ public Map, Object> getChannelOptions() { } @Override - public EventLoopGroup getEventLoopGroup() { + public @Nullable EventLoopGroup getEventLoopGroup() { return eventLoopGroup; } @@ -673,12 +730,12 @@ public boolean isUseOnlyEpollNativeTransport() { } @Override - public ByteBufAllocator getAllocator() { + public @Nullable ByteBufAllocator getAllocator() { return allocator; } @Override - public Timer getNettyTimer() { + public @Nullable Timer getNettyTimer() { return nettyTimer; } @@ -693,17 +750,17 @@ public int getHashedWheelTimerSize() { } @Override - public ThreadFactory getThreadFactory() { + public @Nullable ThreadFactory getThreadFactory() { return threadFactory; } @Override - public Consumer getHttpAdditionalChannelInitializer() { + public @Nullable Consumer getHttpAdditionalChannelInitializer() { return httpAdditionalChannelInitializer; } @Override - public Consumer getWsAdditionalChannelInitializer() { + public @Nullable Consumer getWsAdditionalChannelInitializer() { return wsAdditionalChannelInitializer; } @@ -733,13 +790,13 @@ public static class Builder { private boolean compressionEnforced = defaultCompressionEnforced(); private boolean enableAutomaticDecompression = defaultEnableAutomaticDecompression(); private String userAgent = defaultUserAgent(); - private Realm realm; + private @Nullable Realm realm; private int maxRequestRetry = defaultMaxRequestRetry(); private boolean disableUrlEncodingForBoundRequests = defaultDisableUrlEncodingForBoundRequests(); private boolean useLaxCookieEncoder = defaultUseLaxCookieEncoder(); private boolean disableZeroCopy = defaultDisableZeroCopy(); private boolean keepEncodingHeader = defaultKeepEncodingHeader(); - private ProxyServerSelector proxyServerSelector; + private @Nullable ProxyServerSelector proxyServerSelector; private boolean useProxySelector = defaultUseProxySelector(); private boolean useProxyProperties = defaultUseProxyProperties(); private boolean validateResponseHeaders = defaultValidateResponseHeaders(); @@ -765,8 +822,8 @@ public static class Builder { private int maxConnections = defaultMaxConnections(); private int maxConnectionsPerHost = defaultMaxConnectionsPerHost(); private int acquireFreeChannelTimeout = defaultAcquireFreeChannelTimeout(); - private ChannelPool channelPool; - private ConnectionSemaphoreFactory connectionSemaphoreFactory; + private @Nullable ChannelPool channelPool; + private @Nullable ConnectionSemaphoreFactory connectionSemaphoreFactory; private KeepAliveStrategy keepAliveStrategy = new DefaultKeepAliveStrategy(); // ssl @@ -774,13 +831,13 @@ public static class Builder { private boolean useInsecureTrustManager = defaultUseInsecureTrustManager(); private boolean disableHttpsEndpointIdentificationAlgorithm = defaultDisableHttpsEndpointIdentificationAlgorithm(); private int handshakeTimeout = defaultHandshakeTimeout(); - private String[] enabledProtocols = defaultEnabledProtocols(); - private String[] enabledCipherSuites = defaultEnabledCipherSuites(); + private @Nullable String[] enabledProtocols = defaultEnabledProtocols(); + private @Nullable String[] enabledCipherSuites = defaultEnabledCipherSuites(); private boolean filterInsecureCipherSuites = defaultFilterInsecureCipherSuites(); private int sslSessionCacheSize = defaultSslSessionCacheSize(); private int sslSessionTimeout = defaultSslSessionTimeout(); - private SslContext sslContext; - private SslEngineFactory sslEngineFactory; + private @Nullable SslContext sslContext; + private @Nullable SslEngineFactory sslEngineFactory; // cookie store private CookieStore cookieStore = new ThreadSafeCookieStore(); @@ -803,13 +860,13 @@ public static class Builder { private int chunkedFileChunkSize = defaultChunkedFileChunkSize(); private boolean useNativeTransport = defaultUseNativeTransport(); private boolean useOnlyEpollNativeTransport = defaultUseOnlyEpollNativeTransport(); - private ByteBufAllocator allocator; + private @Nullable ByteBufAllocator allocator; private final Map, Object> channelOptions = new HashMap<>(); - private EventLoopGroup eventLoopGroup; - private Timer nettyTimer; - private ThreadFactory threadFactory; - private Consumer httpAdditionalChannelInitializer; - private Consumer wsAdditionalChannelInitializer; + private @Nullable EventLoopGroup eventLoopGroup; + private @Nullable Timer nettyTimer; + private @Nullable ThreadFactory threadFactory; + private @Nullable Consumer httpAdditionalChannelInitializer; + private @Nullable Consumer wsAdditionalChannelInitializer; private ResponseBodyPartFactory responseBodyPartFactory = ResponseBodyPartFactory.EAGER; private int ioThreadsCount = defaultIoThreadsCount(); private long hashedWheelTickDuration = defaultHashedWheelTimerTickDuration(); diff --git a/client/src/main/java/org/asynchttpclient/DefaultRequest.java b/client/src/main/java/org/asynchttpclient/DefaultRequest.java index a885e67a9..4170c33e2 100644 --- a/client/src/main/java/org/asynchttpclient/DefaultRequest.java +++ b/client/src/main/java/org/asynchttpclient/DefaultRequest.java @@ -23,6 +23,7 @@ import org.asynchttpclient.request.body.generator.BodyGenerator; import org.asynchttpclient.request.body.multipart.Part; import org.asynchttpclient.uri.Uri; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.InputStream; @@ -39,58 +40,58 @@ public class DefaultRequest implements Request { - public final ProxyServer proxyServer; + public final @Nullable ProxyServer proxyServer; private final String method; private final Uri uri; - private final InetAddress address; - private final InetAddress localAddress; + private final @Nullable InetAddress address; + private final @Nullable InetAddress localAddress; private final HttpHeaders headers; private final List cookies; - private final byte[] byteData; - private final List compositeByteData; - private final String stringData; - private final ByteBuffer byteBufferData; - private final InputStream streamData; - private final BodyGenerator bodyGenerator; + private final byte @Nullable [] byteData; + private final @Nullable List compositeByteData; + private final @Nullable String stringData; + private final @Nullable ByteBuffer byteBufferData; + private final @Nullable InputStream streamData; + private final @Nullable BodyGenerator bodyGenerator; private final List formParams; private final List bodyParts; - private final String virtualHost; - private final Realm realm; - private final File file; - private final Boolean followRedirect; + private final @Nullable String virtualHost; + private final @Nullable Realm realm; + private final @Nullable File file; + private final @Nullable Boolean followRedirect; private final Duration requestTimeout; private final Duration readTimeout; private final long rangeOffset; - private final Charset charset; + private final @Nullable Charset charset; private final ChannelPoolPartitioning channelPoolPartitioning; private final NameResolver nameResolver; // lazily loaded - private List queryParams; + private @Nullable List queryParams; public DefaultRequest(String method, Uri uri, - InetAddress address, - InetAddress localAddress, + @Nullable InetAddress address, + @Nullable InetAddress localAddress, HttpHeaders headers, List cookies, - byte[] byteData, - List compositeByteData, - String stringData, - ByteBuffer byteBufferData, - InputStream streamData, - BodyGenerator bodyGenerator, + byte @Nullable [] byteData, + @Nullable List compositeByteData, + @Nullable String stringData, + @Nullable ByteBuffer byteBufferData, + @Nullable InputStream streamData, + @Nullable BodyGenerator bodyGenerator, List formParams, List bodyParts, - String virtualHost, - ProxyServer proxyServer, - Realm realm, - File file, - Boolean followRedirect, - Duration requestTimeout, - Duration readTimeout, + @Nullable String virtualHost, + @Nullable ProxyServer proxyServer, + @Nullable Realm realm, + @Nullable File file, + @Nullable Boolean followRedirect, + @Nullable Duration requestTimeout, + @Nullable Duration readTimeout, long rangeOffset, - Charset charset, + @Nullable Charset charset, ChannelPoolPartitioning channelPoolPartitioning, NameResolver nameResolver) { this.method = method; @@ -136,12 +137,12 @@ public Uri getUri() { } @Override - public InetAddress getAddress() { + public @Nullable InetAddress getAddress() { return address; } @Override - public InetAddress getLocalAddress() { + public @Nullable InetAddress getLocalAddress() { return localAddress; } @@ -156,32 +157,32 @@ public List getCookies() { } @Override - public byte[] getByteData() { + public byte @Nullable [] getByteData() { return byteData; } @Override - public List getCompositeByteData() { + public @Nullable List getCompositeByteData() { return compositeByteData; } @Override - public String getStringData() { + public @Nullable String getStringData() { return stringData; } @Override - public ByteBuffer getByteBufferData() { + public @Nullable ByteBuffer getByteBufferData() { return byteBufferData; } @Override - public InputStream getStreamData() { + public @Nullable InputStream getStreamData() { return streamData; } @Override - public BodyGenerator getBodyGenerator() { + public @Nullable BodyGenerator getBodyGenerator() { return bodyGenerator; } @@ -196,27 +197,27 @@ public List getBodyParts() { } @Override - public String getVirtualHost() { + public @Nullable String getVirtualHost() { return virtualHost; } @Override - public ProxyServer getProxyServer() { + public @Nullable ProxyServer getProxyServer() { return proxyServer; } @Override - public Realm getRealm() { + public @Nullable Realm getRealm() { return realm; } @Override - public File getFile() { + public @Nullable File getFile() { return file; } @Override - public Boolean getFollowRedirect() { + public @Nullable Boolean getFollowRedirect() { return followRedirect; } @@ -236,7 +237,7 @@ public long getRangeOffset() { } @Override - public Charset getCharset() { + public @Nullable Charset getCharset() { return charset; } diff --git a/client/src/main/java/org/asynchttpclient/Param.java b/client/src/main/java/org/asynchttpclient/Param.java index 397d5b5fa..cbc35e196 100644 --- a/client/src/main/java/org/asynchttpclient/Param.java +++ b/client/src/main/java/org/asynchttpclient/Param.java @@ -15,6 +15,8 @@ */ package org.asynchttpclient; +import org.jetbrains.annotations.Nullable; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -27,14 +29,14 @@ public class Param { private final String name; - private final String value; + private final @Nullable String value; - public Param(String name, String value) { + public Param(String name, @Nullable String value) { this.name = name; this.value = value; } - public static List map2ParamList(Map> map) { + public static @Nullable List map2ParamList(Map> map) { if (map == null) { return null; } @@ -53,7 +55,7 @@ public String getName() { return name; } - public String getValue() { + public @Nullable String getValue() { return value; } diff --git a/client/src/main/java/org/asynchttpclient/Realm.java b/client/src/main/java/org/asynchttpclient/Realm.java index 271590da8..2006bd8b8 100644 --- a/client/src/main/java/org/asynchttpclient/Realm.java +++ b/client/src/main/java/org/asynchttpclient/Realm.java @@ -20,6 +20,7 @@ import org.asynchttpclient.util.AuthenticatorUtils; import org.asynchttpclient.util.StringBuilderPool; import org.asynchttpclient.util.StringUtils; +import org.jetbrains.annotations.Nullable; import java.nio.charset.Charset; import java.security.MessageDigest; @@ -45,51 +46,51 @@ public class Realm { // MD5("") private static final String EMPTY_ENTITY_MD5 = "d41d8cd98f00b204e9800998ecf8427e"; - private final String principal; - private final String password; + private final @Nullable String principal; + private final @Nullable String password; private final AuthScheme scheme; - private final String realmName; - private final String nonce; - private final String algorithm; - private final String response; - private final String opaque; - private final String qop; + private final @Nullable String realmName; + private final @Nullable String nonce; + private final @Nullable String algorithm; + private final @Nullable String response; + private final @Nullable String opaque; + private final @Nullable String qop; private final String nc; - private final String cnonce; - private final Uri uri; + private final @Nullable String cnonce; + private final @Nullable Uri uri; private final boolean usePreemptiveAuth; private final Charset charset; private final String ntlmHost; private final String ntlmDomain; private final boolean useAbsoluteURI; private final boolean omitQuery; - private final Map customLoginConfig; - private final String servicePrincipalName; + private final @Nullable Map customLoginConfig; + private final @Nullable String servicePrincipalName; private final boolean useCanonicalHostname; - private final String loginContextName; - - private Realm(AuthScheme scheme, - String principal, - String password, - String realmName, - String nonce, - String algorithm, - String response, - String opaque, - String qop, + private final @Nullable String loginContextName; + + private Realm(@Nullable AuthScheme scheme, + @Nullable String principal, + @Nullable String password, + @Nullable String realmName, + @Nullable String nonce, + @Nullable String algorithm, + @Nullable String response, + @Nullable String opaque, + @Nullable String qop, String nc, - String cnonce, - Uri uri, + @Nullable String cnonce, + @Nullable Uri uri, boolean usePreemptiveAuth, Charset charset, String ntlmDomain, String ntlmHost, boolean useAbsoluteURI, boolean omitQuery, - String servicePrincipalName, + @Nullable String servicePrincipalName, boolean useCanonicalHostname, - Map customLoginConfig, - String loginContextName) { + @Nullable Map customLoginConfig, + @Nullable String loginContextName) { this.scheme = assertNotNull(scheme, "scheme"); this.principal = principal; @@ -115,11 +116,11 @@ private Realm(AuthScheme scheme, this.loginContextName = loginContextName; } - public String getPrincipal() { + public @Nullable String getPrincipal() { return principal; } - public String getPassword() { + public @Nullable String getPassword() { return password; } @@ -127,27 +128,27 @@ public AuthScheme getScheme() { return scheme; } - public String getRealmName() { + public @Nullable String getRealmName() { return realmName; } - public String getNonce() { + public @Nullable String getNonce() { return nonce; } - public String getAlgorithm() { + public @Nullable String getAlgorithm() { return algorithm; } - public String getResponse() { + public @Nullable String getResponse() { return response; } - public String getOpaque() { + public @Nullable String getOpaque() { return opaque; } - public String getQop() { + public @Nullable String getQop() { return qop; } @@ -155,11 +156,11 @@ public String getNc() { return nc; } - public String getCnonce() { + public @Nullable String getCnonce() { return cnonce; } - public Uri getUri() { + public @Nullable Uri getUri() { return uri; } @@ -202,11 +203,11 @@ public boolean isOmitQuery() { return omitQuery; } - public Map getCustomLoginConfig() { + public @Nullable Map getCustomLoginConfig() { return customLoginConfig; } - public String getServicePrincipalName() { + public @Nullable String getServicePrincipalName() { return servicePrincipalName; } @@ -214,7 +215,7 @@ public boolean isUseCanonicalHostname() { return useCanonicalHostname; } - public String getLoginContextName() { + public @Nullable String getLoginContextName() { return loginContextName; } @@ -255,18 +256,18 @@ public enum AuthScheme { */ public static class Builder { - private final String principal; - private final String password; - private AuthScheme scheme; - private String realmName; - private String nonce; - private String algorithm; - private String response; - private String opaque; - private String qop; + private final @Nullable String principal; + private final @Nullable String password; + private @Nullable AuthScheme scheme; + private @Nullable String realmName; + private @Nullable String nonce; + private @Nullable String algorithm; + private @Nullable String response; + private @Nullable String opaque; + private @Nullable String qop; private String nc = DEFAULT_NC; - private String cnonce; - private Uri uri; + private @Nullable String cnonce; + private @Nullable Uri uri; private String methodName = GET; private boolean usePreemptive; private String ntlmDomain = System.getProperty("http.auth.ntlm.domain"); @@ -277,17 +278,17 @@ public static class Builder { /** * Kerberos/Spnego properties */ - private Map customLoginConfig; - private String servicePrincipalName; + private @Nullable Map customLoginConfig; + private @Nullable String servicePrincipalName; private boolean useCanonicalHostname; - private String loginContextName; + private @Nullable String loginContextName; public Builder() { principal = null; password = null; } - public Builder(String principal, String password) { + public Builder(@Nullable String principal, @Nullable String password) { this.principal = principal; this.password = password; } @@ -307,17 +308,17 @@ public Builder setScheme(AuthScheme scheme) { return this; } - public Builder setRealmName(String realmName) { + public Builder setRealmName(@Nullable String realmName) { this.realmName = realmName; return this; } - public Builder setNonce(String nonce) { + public Builder setNonce(@Nullable String nonce) { this.nonce = nonce; return this; } - public Builder setAlgorithm(String algorithm) { + public Builder setAlgorithm(@Nullable String algorithm) { this.algorithm = algorithm; return this; } @@ -327,12 +328,12 @@ public Builder setResponse(String response) { return this; } - public Builder setOpaque(String opaque) { + public Builder setOpaque(@Nullable String opaque) { this.opaque = opaque; return this; } - public Builder setQop(String qop) { + public Builder setQop(@Nullable String qop) { if (isNonEmpty(qop)) { this.qop = qop; } @@ -344,7 +345,7 @@ public Builder setNc(String nc) { return this; } - public Builder setUri(Uri uri) { + public Builder setUri(@Nullable Uri uri) { this.uri = uri; return this; } @@ -374,12 +375,12 @@ public Builder setCharset(Charset charset) { return this; } - public Builder setCustomLoginConfig(Map customLoginConfig) { + public Builder setCustomLoginConfig(@Nullable Map customLoginConfig) { this.customLoginConfig = customLoginConfig; return this; } - public Builder setServicePrincipalName(String servicePrincipalName) { + public Builder setServicePrincipalName(@Nullable String servicePrincipalName) { this.servicePrincipalName = servicePrincipalName; return this; } @@ -389,12 +390,12 @@ public Builder setUseCanonicalHostname(boolean useCanonicalHostname) { return this; } - public Builder setLoginContextName(String loginContextName) { + public Builder setLoginContextName(@Nullable String loginContextName) { this.loginContextName = loginContextName; return this; } - private static String parseRawQop(String rawQop) { + private static @Nullable String parseRawQop(String rawQop) { String[] rawServerSupportedQops = rawQop.split(","); String[] serverSupportedQops = new String[rawServerSupportedQops.length]; for (int i = 0; i < rawServerSupportedQops.length; i++) { @@ -461,7 +462,7 @@ private void newCnonce(MessageDigest md) { /** * TODO: A Pattern/Matcher may be better. */ - private static String match(String headerLine, String token) { + private static @Nullable String match(String headerLine, String token) { if (headerLine == null) { return null; } diff --git a/client/src/main/java/org/asynchttpclient/Request.java b/client/src/main/java/org/asynchttpclient/Request.java index 42d53cb8e..0f8cdaa06 100644 --- a/client/src/main/java/org/asynchttpclient/Request.java +++ b/client/src/main/java/org/asynchttpclient/Request.java @@ -24,6 +24,7 @@ import org.asynchttpclient.request.body.generator.BodyGenerator; import org.asynchttpclient.request.body.multipart.Part; import org.asynchttpclient.uri.Uri; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.InputStream; @@ -65,12 +66,12 @@ public interface Request { /** * @return the InetAddress to be used to bypass uri's hostname resolution */ - InetAddress getAddress(); + @Nullable InetAddress getAddress(); /** * @return the local address to bind from */ - InetAddress getLocalAddress(); + @Nullable InetAddress getLocalAddress(); /** * @return the HTTP headers @@ -85,32 +86,32 @@ public interface Request { /** * @return the request's body byte array (only non null if it was set this way) */ - byte[] getByteData(); + byte @Nullable [] getByteData(); /** * @return the request's body array of byte arrays (only non null if it was set this way) */ - List getCompositeByteData(); + @Nullable List getCompositeByteData(); /** * @return the request's body string (only non null if it was set this way) */ - String getStringData(); + @Nullable String getStringData(); /** * @return the request's body ByteBuffer (only non null if it was set this way) */ - ByteBuffer getByteBufferData(); + @Nullable ByteBuffer getByteBufferData(); /** * @return the request's body InputStream (only non null if it was set this way) */ - InputStream getStreamData(); + @Nullable InputStream getStreamData(); /** * @return the request's body BodyGenerator (only non null if it was set this way) */ - BodyGenerator getBodyGenerator(); + @Nullable BodyGenerator getBodyGenerator(); /** * @return the request's form parameters @@ -125,7 +126,7 @@ public interface Request { /** * @return the virtual host to connect to */ - String getVirtualHost(); + @Nullable String getVirtualHost(); /** * @return the query params resolved from the url/uri @@ -135,22 +136,22 @@ public interface Request { /** * @return the proxy server to be used to perform this request (overrides the one defined in config) */ - ProxyServer getProxyServer(); + @Nullable ProxyServer getProxyServer(); /** * @return the realm to be used to perform this request (overrides the one defined in config) */ - Realm getRealm(); + @Nullable Realm getRealm(); /** * @return the file to be uploaded */ - File getFile(); + @Nullable File getFile(); /** * @return if this request is to follow redirects. Non null values means "override config value". */ - Boolean getFollowRedirect(); + @Nullable Boolean getFollowRedirect(); /** * @return the request timeout. Non zero values means "override config value". @@ -170,7 +171,7 @@ public interface Request { /** * @return the charset value used when decoding the request's body. */ - Charset getCharset(); + @Nullable Charset getCharset(); /** * @return the strategy to compute ChannelPool's keys diff --git a/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java b/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java index 059d9fe8b..0be0a8f44 100644 --- a/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java +++ b/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java @@ -26,7 +26,9 @@ import org.asynchttpclient.request.body.generator.BodyGenerator; import org.asynchttpclient.request.body.multipart.Part; import org.asynchttpclient.uri.Uri; +import org.asynchttpclient.util.EnsuresNonNull; import org.asynchttpclient.util.UriEncoder; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,33 +62,33 @@ public abstract class RequestBuilderBase> { public static final NameResolver DEFAULT_NAME_RESOLVER = new DefaultNameResolver(ImmediateEventExecutor.INSTANCE); // builder only fields protected UriEncoder uriEncoder; - protected List queryParams; - protected SignatureCalculator signatureCalculator; + protected @Nullable List queryParams; + protected @Nullable SignatureCalculator signatureCalculator; // request fields protected String method; - protected Uri uri; - protected InetAddress address; - protected InetAddress localAddress; + protected @Nullable Uri uri; + protected @Nullable InetAddress address; + protected @Nullable InetAddress localAddress; protected HttpHeaders headers; - protected ArrayList cookies; - protected byte[] byteData; - protected List compositeByteData; - protected String stringData; - protected ByteBuffer byteBufferData; - protected InputStream streamData; - protected BodyGenerator bodyGenerator; - protected List formParams; - protected List bodyParts; - protected String virtualHost; - protected ProxyServer proxyServer; - protected Realm realm; - protected File file; - protected Boolean followRedirect; - protected Duration requestTimeout; - protected Duration readTimeout; + protected @Nullable ArrayList cookies; + protected byte @Nullable [] byteData; + protected @Nullable List compositeByteData; + protected @Nullable String stringData; + protected @Nullable ByteBuffer byteBufferData; + protected @Nullable InputStream streamData; + protected @Nullable BodyGenerator bodyGenerator; + protected @Nullable List formParams; + protected @Nullable List bodyParts; + protected @Nullable String virtualHost; + protected @Nullable ProxyServer proxyServer; + protected @Nullable Realm realm; + protected @Nullable File file; + protected @Nullable Boolean followRedirect; + protected @Nullable Duration requestTimeout; + protected @Nullable Duration readTimeout; protected long rangeOffset; - protected Charset charset; + protected @Nullable Charset charset; protected ChannelPoolPartitioning channelPoolPartitioning = ChannelPoolPartitioning.PerHostChannelPoolPartitioning.INSTANCE; protected NameResolver nameResolver = DEFAULT_NAME_RESOLVER; @@ -293,6 +295,7 @@ public T setSingleHeaders(Map headers) { return asDerivedType(); } + @EnsuresNonNull("cookies") private void lazyInitCookies() { if (cookies == null) { cookies = new ArrayList<>(3); @@ -413,6 +416,7 @@ public T setBody(BodyGenerator bodyGenerator) { return asDerivedType(); } + @EnsuresNonNull("queryParams") public T addQueryParam(String name, String value) { if (queryParams == null) { queryParams = new ArrayList<>(1); @@ -421,6 +425,7 @@ public T addQueryParam(String name, String value) { return asDerivedType(); } + @EnsuresNonNull("queryParams") public T addQueryParams(List params) { if (queryParams == null) { queryParams = params; @@ -434,7 +439,7 @@ public T setQueryParams(Map> map) { return setQueryParams(Param.map2ParamList(map)); } - public T setQueryParams(List params) { + public T setQueryParams(@Nullable List params) { // reset existing query if (uri != null && isNonEmpty(uri.getQuery())) { uri = uri.withNewQuery(null); @@ -443,6 +448,7 @@ public T setQueryParams(List params) { return asDerivedType(); } + @EnsuresNonNull("formParams") public T addFormParam(String name, String value) { resetNonMultipartData(); resetMultipartData(); @@ -457,13 +463,14 @@ public T setFormParams(Map> map) { return setFormParams(Param.map2ParamList(map)); } - public T setFormParams(List params) { + public T setFormParams(@Nullable List params) { resetNonMultipartData(); resetMultipartData(); formParams = params; return asDerivedType(); } + @EnsuresNonNull("bodyParts") public T addBodyPart(Part bodyPart) { resetFormParams(); resetNonMultipartData(); @@ -474,6 +481,7 @@ public T addBodyPart(Part bodyPart) { return asDerivedType(); } + @EnsuresNonNull("bodyParts") public T setBodyParts(List bodyParts) { this.bodyParts = new ArrayList<>(bodyParts); return asDerivedType(); @@ -539,7 +547,7 @@ public T setNameResolver(NameResolver nameResolver) { return asDerivedType(); } - public T setSignatureCalculator(SignatureCalculator signatureCalculator) { + public T setSignatureCalculator(@Nullable SignatureCalculator signatureCalculator) { this.signatureCalculator = signatureCalculator; return asDerivedType(); } @@ -595,6 +603,7 @@ private RequestBuilderBase executeSignatureCalculator() { return rb; } + @EnsuresNonNull("charset") private void updateCharset() { String contentTypeHeader = headers.get(CONTENT_TYPE); Charset contentTypeCharset = extractContentTypeCharsetAttribute(contentTypeHeader); diff --git a/client/src/main/java/org/asynchttpclient/Response.java b/client/src/main/java/org/asynchttpclient/Response.java index 78a257e9c..8b9c9a6f1 100644 --- a/client/src/main/java/org/asynchttpclient/Response.java +++ b/client/src/main/java/org/asynchttpclient/Response.java @@ -20,6 +20,7 @@ import io.netty.handler.codec.http.cookie.Cookie; import org.asynchttpclient.netty.NettyResponse; import org.asynchttpclient.uri.Uri; +import org.jetbrains.annotations.Nullable; import java.io.InputStream; import java.net.SocketAddress; @@ -176,8 +177,8 @@ public interface Response { class ResponseBuilder { private final List bodyParts = new ArrayList<>(1); - private HttpResponseStatus status; - private HttpHeaders headers; + private @Nullable HttpResponseStatus status; + private @Nullable HttpHeaders headers; public void accumulate(HttpResponseStatus status) { this.status = status; @@ -201,7 +202,7 @@ public void accumulate(HttpResponseBodyPart bodyPart) { * * @return a {@link Response} instance */ - public Response build() { + public @Nullable Response build() { return status == null ? null : new NettyResponse(status, headers, bodyParts); } diff --git a/client/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java b/client/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java index 9363917a2..54401091f 100644 --- a/client/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java +++ b/client/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java @@ -21,6 +21,7 @@ import org.asynchttpclient.util.StringBuilderPool; import org.asynchttpclient.util.StringUtils; import org.asynchttpclient.util.Utf8UrlEncoder; +import org.jetbrains.annotations.Nullable; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -155,7 +156,7 @@ private String encodedParams(ConsumerKey consumerAuth, RequestToken userAuth, lo return parameters.sortAndConcat(); } - private static String percentEncodeAlreadyFormUrlEncoded(String s) { + private static String percentEncodeAlreadyFormUrlEncoded(@Nullable String s) { if (s == null) { return ""; } diff --git a/client/src/main/java/org/asynchttpclient/util/EnsuresNonNull.java b/client/src/main/java/org/asynchttpclient/util/EnsuresNonNull.java new file mode 100644 index 000000000..a0cecaf8e --- /dev/null +++ b/client/src/main/java/org/asynchttpclient/util/EnsuresNonNull.java @@ -0,0 +1,17 @@ +package org.asynchttpclient.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * NullAway supports @EnsuresNonNull(param) annotation, but org.jetbrains.annotations doesn't include this annotation. + * The purpose of this annotation is to tell NullAway that if the annotated method succeeded without any exceptions, + * all class's fields defined in "param" will be @NotNull. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface EnsuresNonNull { + String[] value(); +} diff --git a/pom.xml b/pom.xml index 0e6809729..d5ee16304 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,7 @@ 2.0.5 2.0.1 1.4.5 + 24.0.1 @@ -203,7 +204,7 @@ org.jetbrains annotations - 24.0.1 + ${jetbrains-annotations.version} @@ -231,7 +232,8 @@ -Xep:NullablePrimitive:ERROR -Xep:NullOptional:ERROR -XepExcludedPaths:.*/src/test/java/.* - -XepOpt:NullAway:AnnotatedPackages=org.asynchttpclient.channel,org.asynchttpclient.config,org.asynchttpclient.cookie,org.asynchttpclient.exception,org.asynchttpclient.filter,org.asynchttpclient.oauth,org.asynchttpclient.proxy,org.asynchttpclient.resolver + -XepOpt:NullAway:AnnotatedPackages=org.asynchttpclient + -XepOpt:NullAway:UnannotatedSubPackages=org.asynchttpclient.handler,org.asynchttpclient.netty,org.asynchttpclient.ntlm,org.asynchttpclient.request,org.asynchttpclient.spnego,org.asynchttpclient.uri,org.asynchttpclient.util,org.asynchttpclient.webdav,org.asynchttpclient.ws -XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=true -Xep:NullAway:ERROR