You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2024/10/01 08:33:52 UTC

(httpcomponents-core) 01/05: Refactor to use a new class CompletingFutureContribution (#484)

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 42e2d142feeb513218e33cd8b0bd970c4e159af3
Author: Gary Gregory <ga...@users.noreply.github.com>
AuthorDate: Mon Sep 23 19:30:46 2024 -0400

    Refactor to use a new class CompletingFutureContribution (#484)
    
    - Reduces boilerplate when the same pattern is used
---
 .../nio/bootstrap/H2MultiplexingRequester.java     | 11 ++----
 .../core5/testing/nio/ClientSessionEndpoint.java   | 11 ++----
 .../apache/hc/core5/testing/nio/H2TestClient.java  | 12 ++-----
 .../hc/core5/testing/nio/Http1TestClient.java      | 12 ++-----
 .../hc/core5/testing/nio/TLSIntegrationTest.java   | 10 ++----
 .../hc/core5/testing/nio/TLSUpgradeTest.java       | 11 ++----
 ...tion.java => CompletingFutureContribution.java} | 41 +++++++++++++---------
 .../hc/core5/concurrent/FutureContribution.java    |  7 +++-
 .../http/impl/bootstrap/HttpAsyncRequester.java    | 11 ++----
 .../hc/core5/http/nio/AsyncClientEndpoint.java     | 11 ++----
 .../hc/core5/reactor/AbstractIOSessionPool.java    | 11 ++----
 .../apache/hc/core5/reactor/ProtocolIOSession.java |  3 +-
 12 files changed, 49 insertions(+), 102 deletions(-)

diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2MultiplexingRequester.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2MultiplexingRequester.java
index 4e6b14e4e..90103e65b 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2MultiplexingRequester.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2MultiplexingRequester.java
@@ -37,9 +37,9 @@ import java.util.concurrent.Future;
 import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.concurrent.Cancellable;
 import org.apache.hc.core5.concurrent.CancellableDependency;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.ComplexFuture;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.function.Decorator;
 import org.apache.hc.core5.function.Resolver;
@@ -282,14 +282,7 @@ public class H2MultiplexingRequester extends AsyncRequester {
         final AsyncClientExchangeHandler exchangeHandler = new BasicClientExchangeHandler<>(
                 requestProducer,
                 responseConsumer,
-                new FutureContribution<T>(future) {
-
-                    @Override
-                    public void completed(final T result) {
-                        future.completed(result);
-                    }
-
-                });
+                new CompletingFutureContribution<T, T>(future));
         execute(target, exchangeHandler, pushHandlerFactory, future, timeout, context != null ? context : HttpCoreContext.create());
         return future;
     }
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/ClientSessionEndpoint.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/ClientSessionEndpoint.java
index ba3761b66..f81e5354d 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/ClientSessionEndpoint.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/ClientSessionEndpoint.java
@@ -34,8 +34,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.http.ConnectionClosedException;
 import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
 import org.apache.hc.core5.http.nio.AsyncPushConsumer;
@@ -103,14 +103,7 @@ public final class ClientSessionEndpoint implements ModalCloseable {
         Asserts.check(!closed.get(), "Connection is already closed");
         final BasicFuture<T> future = new BasicFuture<>(callback);
         execute(new BasicClientExchangeHandler<>(requestProducer, responseConsumer,
-                new FutureContribution<T>(future) {
-
-                    @Override
-                    public void completed(final T result) {
-                        future.completed(result);
-                    }
-
-                }),
+                new CompletingFutureContribution<T, T>(future)),
                 pushHandlerFactory, context);
         return future;
     }
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/H2TestClient.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/H2TestClient.java
index a8839f838..37a636aa4 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/H2TestClient.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/H2TestClient.java
@@ -35,8 +35,8 @@ import java.util.concurrent.Future;
 import javax.net.ssl.SSLContext;
 
 import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.config.CharCodingConfig;
@@ -53,7 +53,6 @@ import org.apache.hc.core5.http2.nio.support.DefaultAsyncPushConsumerFactory;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOReactorStatus;
-import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
 import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
 import org.apache.hc.core5.util.Args;
@@ -209,14 +208,7 @@ public class H2TestClient extends AsyncRequester {
             final Timeout timeout,
             final FutureCallback<ClientSessionEndpoint> callback) {
         final BasicFuture<ClientSessionEndpoint> future = new BasicFuture<>(callback);
-        requestSession(host, timeout, new FutureContribution<IOSession>(future) {
-
-            @Override
-            public void completed(final IOSession session) {
-                future.completed(new ClientSessionEndpoint(session));
-            }
-
-        });
+        requestSession(host, timeout, new CompletingFutureContribution<>(future, ClientSessionEndpoint::new));
         return future;
     }
 
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http1TestClient.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http1TestClient.java
index 674fbd43e..abb896cc9 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http1TestClient.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http1TestClient.java
@@ -33,8 +33,8 @@ import java.util.concurrent.Future;
 import javax.net.ssl.SSLContext;
 
 import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.config.CharCodingConfig;
 import org.apache.hc.core5.http.config.Http1Config;
@@ -43,7 +43,6 @@ import org.apache.hc.core5.http.impl.HttpProcessors;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOReactorStatus;
-import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
 import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
 import org.apache.hc.core5.util.Asserts;
@@ -129,14 +128,7 @@ public class Http1TestClient extends AsyncRequester {
             final Timeout timeout,
             final FutureCallback<ClientSessionEndpoint> callback) {
         final BasicFuture<ClientSessionEndpoint> future = new BasicFuture<>(callback);
-        requestSession(host, timeout, new FutureContribution<IOSession>(future) {
-
-            @Override
-            public void completed(final IOSession session) {
-                future.completed(new ClientSessionEndpoint(session));
-            }
-
-        });
+        requestSession(host, timeout, new CompletingFutureContribution<>(future, ClientSessionEndpoint::new));
         return future;
     }
 
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSIntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSIntegrationTest.java
index f4e033399..d1d54687c 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSIntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSIntegrationTest.java
@@ -40,6 +40,7 @@ import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLSession;
 
 import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.FutureCallback;
 import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.function.Supplier;
@@ -185,14 +186,7 @@ class TLSIntegrationTest {
                         try {
                             ((TlsUpgradeCapable) clientEndpoint).tlsUpgrade(
                                     target,
-                                    new FutureContribution<ProtocolIOSession>(tlsFuture) {
-
-                                        @Override
-                                        public void completed(final ProtocolIOSession protocolIOSession) {
-                                            tlsFuture.completed(protocolIOSession.getTlsDetails());
-                                        }
-
-                                    });
+                                    new CompletingFutureContribution<>(tlsFuture, ProtocolIOSession::getTlsDetails));
                         } catch (final Exception ex) {
                             tlsFuture.failed(ex);
                         }
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSUpgradeTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSUpgradeTest.java
index 1c554e33c..8e52db309 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSUpgradeTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TLSUpgradeTest.java
@@ -33,7 +33,7 @@ import java.net.InetSocketAddress;
 import java.util.concurrent.Future;
 
 import org.apache.hc.core5.concurrent.BasicFuture;
-import org.apache.hc.core5.concurrent.FutureContribution;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.HttpHost;
@@ -120,14 +120,7 @@ class TLSUpgradeTest {
 
         // Upgrade to TLS
         final BasicFuture<TlsDetails> tlsFuture = new BasicFuture<>(null);
-        ((TlsUpgradeCapable) clientEndpoint).tlsUpgrade(target, new FutureContribution<ProtocolIOSession>(tlsFuture) {
-
-            @Override
-            public void completed(final ProtocolIOSession protocolIOSession) {
-                tlsFuture.completed(protocolIOSession.getTlsDetails());
-            }
-
-        });
+        ((TlsUpgradeCapable) clientEndpoint).tlsUpgrade(target, new CompletingFutureContribution<>(tlsFuture, ProtocolIOSession::getTlsDetails));
 
         final TlsDetails tlsDetails = tlsFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
         Assertions.assertNotNull(tlsDetails);
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java b/httpcore5/src/main/java/org/apache/hc/core5/concurrent/CompletingFutureContribution.java
similarity index 57%
copy from httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java
copy to httpcore5/src/main/java/org/apache/hc/core5/concurrent/CompletingFutureContribution.java
index 88cd68b5b..79ff607d5 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/concurrent/CompletingFutureContribution.java
@@ -24,40 +24,47 @@
  * <http://www.apache.org/>.
  *
  */
+
 package org.apache.hc.core5.concurrent;
 
+import java.util.Objects;
+import java.util.function.Function;
+
 /**
- * Convenience base class for {@link FutureCallback}s that contribute a result
- * of the operation to another {@link BasicFuture}.
+ * Completes a result on a {@link BasicFuture}.
  *
- * @param <T> the future result type of an asynchronous operation.
- * @since 5.1
+ * @param <T> the future result type of an asynchronous operation for this type.
+ * @param <U> the future result type of an asynchronous operation for the {@link FutureCallback}.
+ * @since 5.4
  */
-public abstract class FutureContribution<T> implements FutureCallback<T> {
+public class CompletingFutureContribution<T, U> extends FutureContribution<T> {
 
-    private final BasicFuture<?> future;
+    private final Function<T, U> resultProvider;
 
     /**
      * Constructs a new instance to callback the given {@link BasicFuture}.
      *
      * @param future The callback.
      */
-    public FutureContribution(final BasicFuture<?> future) {
-        this.future = future;
+    @SuppressWarnings("unchecked")
+    public CompletingFutureContribution(final BasicFuture<U> future) {
+        this(future, (Function<T, U>) Function.identity());
     }
 
-    @Override
-    public final void failed(final Exception ex) {
-        if (future != null) {
-            future.failed(ex);
-        }
+    /**
+     * Constructs a new instance to callback the given {@link BasicFuture}.
+     *
+     * @param future The callback.
+     * @param resultProvider Provides the result to complete the future.
+     */
+    public CompletingFutureContribution(final BasicFuture<U> future, final Function<T, U> resultProvider) {
+        super(future);
+        this.resultProvider = Objects.requireNonNull(resultProvider, "resultProvider");
     }
 
     @Override
-    public final void cancelled() {
-        if (future != null) {
-            future.cancel();
-        }
+    public void completed(final T result) {
+        getFuture().completed(resultProvider.apply(result));
     }
 
 }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java b/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java
index 88cd68b5b..fde61517e 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureContribution.java
@@ -30,7 +30,7 @@ package org.apache.hc.core5.concurrent;
  * Convenience base class for {@link FutureCallback}s that contribute a result
  * of the operation to another {@link BasicFuture}.
  *
- * @param <T> the future result type of an asynchronous operation.
+ * @param <T> the future result type of an asynchronous operation for this type.
  * @since 5.1
  */
 public abstract class FutureContribution<T> implements FutureCallback<T> {
@@ -60,4 +60,9 @@ public abstract class FutureContribution<T> implements FutureCallback<T> {
         }
     }
 
+    @SuppressWarnings("unchecked")
+    <R> BasicFuture<R> getFuture() {
+        return (BasicFuture<R>) future;
+    }
+
 }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
index 1f856f12e..059ee8f44 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
@@ -37,9 +37,9 @@ import java.util.concurrent.atomic.AtomicReference;
 import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.concurrent.BasicFuture;
 import org.apache.hc.core5.concurrent.CallbackContribution;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.ComplexFuture;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.function.Decorator;
 import org.apache.hc.core5.http.ConnectionClosedException;
@@ -417,14 +417,7 @@ public class HttpAsyncRequester extends AsyncRequester implements ConnPoolContro
         final AsyncClientExchangeHandler exchangeHandler = new BasicClientExchangeHandler<>(
                 requestProducer,
                 responseConsumer,
-                new FutureContribution<T>(future) {
-
-                    @Override
-                    public void completed(final T result) {
-                        future.completed(result);
-                    }
-
-                });
+                new CompletingFutureContribution<T, T>(future));
         execute(target, exchangeHandler, pushHandlerFactory, timeout, context != null ? context : HttpCoreContext.create());
         return future;
     }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncClientEndpoint.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncClientEndpoint.java
index 749bf32c2..94def76b9 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncClientEndpoint.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncClientEndpoint.java
@@ -32,8 +32,8 @@ import java.util.concurrent.Future;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.http.nio.support.BasicClientExchangeHandler;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
@@ -101,14 +101,7 @@ public abstract class AsyncClientEndpoint {
             final FutureCallback<T> callback) {
         final BasicFuture<T> future = new BasicFuture<>(callback);
         execute(new BasicClientExchangeHandler<>(requestProducer, responseConsumer,
-                        new FutureContribution<T>(future) {
-
-                            @Override
-                            public void completed(final T result) {
-                                future.completed(result);
-                            }
-
-                        }),
+                        new CompletingFutureContribution<T, T>(future)),
                 pushHandlerFactory, context != null ? context : HttpCoreContext.create());
         return future;
     }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java
index 3691264aa..a7c7cffa0 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractIOSessionPool.java
@@ -38,9 +38,9 @@ import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.concurrent.CompletingFutureContribution;
 import org.apache.hc.core5.concurrent.ComplexFuture;
 import org.apache.hc.core5.concurrent.FutureCallback;
-import org.apache.hc.core5.concurrent.FutureContribution;
 import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.http.ConnectionClosedException;
 import org.apache.hc.core5.io.CloseMode;
@@ -145,14 +145,7 @@ public abstract class AbstractIOSessionPool<T> implements ModalCloseable {
                         future.completed(ioSession);
                     } else {
                         getSessionInternal(poolEntry, true, endpoint, connectTimeout,
-                            new FutureContribution<IOSession>(future) {
-
-                            @Override
-                            public void completed(final IOSession ioSession1) {
-                                future.completed(ioSession1);
-                            }
-
-                        });
+                            new CompletingFutureContribution<>(future));
                     }
                 });
             }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java
index cebfb06d9..7996a7bd4 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java
@@ -40,6 +40,7 @@ public interface ProtocolIOSession extends IOSession, TransportSecurityLayer {
 
     /**
      * Switches this I/O session to the application protocol with the given ID.
+     *
      * @param protocolId the application protocol ID
      * @param callback the result callback
      * @throws UnsupportedOperationException if application protocol switch
@@ -52,10 +53,8 @@ public interface ProtocolIOSession extends IOSession, TransportSecurityLayer {
     /**
      * Registers protocol upgrade handler with the given application protocol ID.
      *
-     * @since 5.2
      * @param protocolId the application protocol ID
      * @param upgradeHandler the upgrade handler.
-     *
      * @since 5.2
      */
     default void registerProtocol(String protocolId, ProtocolUpgradeHandler upgradeHandler) {