3737import java .time .Duration ;
3838import java .util .*;
3939import java .util .concurrent .CompletableFuture ;
40+ import java .util .concurrent .CompletionException ;
4041import java .util .concurrent .TimeUnit ;
4142import java .util .function .Consumer ;
4243import java .util .function .Function ;
@@ -560,7 +561,7 @@ public static Builder contentTypeHeader(Builder builder, String contentType) {
560561 * @return HttpResponse
561562 */
562563 public static HttpResponse <InputStream > execute (HttpClient httpClient , HttpRequest httpRequest ) {
563- return execute ( httpClient , httpRequest , BodyHandlers .ofInputStream ());
564+ return AsyncHttpRDF . getOrElseThrow ( executeAsync ( httpClient , httpRequest , BodyHandlers .ofInputStream ()), httpRequest );
564565 }
565566
566567 /**
@@ -580,13 +581,35 @@ public static HttpResponse<InputStream> execute(HttpClient httpClient, HttpReque
580581 *
581582 * @param httpClient
582583 * @param httpRequest
583- * @param bodyHandler
584584 * @return HttpResponse
585585 */
586- /*package*/ static <X > HttpResponse <X > execute (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <X > bodyHandler ) {
586+ public static CompletableFuture <HttpResponse <InputStream >> executeAsync (HttpClient httpClient , HttpRequest httpRequest ) {
587+ return executeAsync (httpClient , httpRequest , BodyHandlers .ofInputStream ());
588+ }
589+
590+ /**
591+ * Execute a request, return a {@code HttpResponse<X>} which
592+ * can be passed to {@link #handleHttpStatusCode(HttpResponse)} which will
593+ * convert non-2xx status code to {@link HttpException HttpExceptions}.
594+ * <p>
595+ * This function applies the HTTP authentication challenge support
596+ * and will repeat the request if necessary with added authentication.
597+ * <p>
598+ * See {@link AuthEnv} for authentication registration.
599+ * <br/>
600+ * See {@link #executeJDK} to execute exactly once without challenge response handling.
601+ *
602+ * @see AuthEnv AuthEnv for authentic registration
603+ * @see #executeJDK executeJDK to execute exacly once.
604+ *
605+ * @param httpClient
606+ * @param httpRequest
607+ * @param bodyHandler
608+ * @return HttpResponse
609+ */ /*package*/ static <X > CompletableFuture <HttpResponse <X >> executeAsync (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <X > bodyHandler ) {
587610 // To run with no jena-supplied authentication handling.
588611 if ( false )
589- return executeJDK (httpClient , httpRequest , bodyHandler );
612+ return executeJDKAsync (httpClient , httpRequest , bodyHandler );
590613 URI uri = httpRequest .uri ();
591614 URI key = null ;
592615
@@ -602,29 +625,16 @@ public static HttpResponse<InputStream> execute(HttpClient httpClient, HttpReque
602625 authEnv .registerUsernamePassword (key , userpasswd [0 ], userpasswd [1 ]);
603626 }
604627 }
605- try {
606- return AuthLib .authExecute (httpClient , httpRequest , bodyHandler );
607- } finally {
608- if ( key != null )
609- // The AuthEnv is "per tenant".
610- // Temporary registration within the AuthEnv of the
611- // user:password is acceptable.
612- authEnv .unregisterUsernamePassword (key );
613- }
614- }
615628
616- /**
617- * Execute request and return a {@code HttpResponse<InputStream>} response.
618- * Status codes have not been handled. The response can be passed to
619- * {@link #handleResponseInputStream(HttpResponse)} which will convert non-2xx
620- * status code to {@link HttpException HttpExceptions}.
621- *
622- * @param httpClient
623- * @param httpRequest
624- * @return HttpResponse
625- */
626- public static HttpResponse <InputStream > executeJDK (HttpClient httpClient , HttpRequest httpRequest ) {
627- return execute (httpClient , httpRequest , BodyHandlers .ofInputStream ());
629+ URI finalKey = key ;
630+ return AuthLib .authExecuteAsync (httpClient , httpRequest , bodyHandler )
631+ .whenComplete ((httpResponse , throwable ) -> {
632+ if ( finalKey != null )
633+ // The AuthEnv is "per tenant".
634+ // Temporary registration within the AuthEnv of the
635+ // user:password is acceptable.
636+ authEnv .unregisterUsernamePassword (finalKey );
637+ });
628638 }
629639
630640 /**
@@ -640,25 +650,32 @@ public static HttpResponse<InputStream> executeJDK(HttpClient httpClient, HttpRe
640650 * @return HttpResponse
641651 */
642652 public static <T > HttpResponse <T > executeJDK (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <T > bodyHandler ) {
643- try {
644- // This is the one place all HTTP requests go through.
645- logRequest (httpRequest );
646- HttpResponse <T > httpResponse = httpClient .send (httpRequest , bodyHandler );
647- logResponse (httpResponse );
648- return httpResponse ;
649- //} catch (HttpTimeoutException ex) {
650- } catch (IOException | InterruptedException ex ) {
651- if ( ex .getMessage () != null ) {
652- // This is silly.
653- // Rather than an HTTP exception, bad authentication becomes IOException("too many authentication attempts");
654- // or IOException("No credentials provided") if the authenticator decides to return null.
655- if ( ex .getMessage ().contains ("too many authentication attempts" ) ||
656- ex .getMessage ().contains ("No credentials provided" ) ) {
657- throw new HttpException (401 , HttpSC .getMessage (401 ));
658- }
659- }
660- throw new HttpException (httpRequest .method ()+" " +httpRequest .uri ().toString (), ex );
661- }
653+ return AsyncHttpRDF .getOrElseThrow (executeJDKAsync (httpClient , httpRequest , bodyHandler ), httpRequest );
654+ }
655+
656+ /**
657+ * Execute request and return a {@code HttpResponse<InputStream>} response.
658+ * Status codes have not been handled. The response can be passed to
659+ * {@link #handleResponseInputStream(HttpResponse)} which will convert non-2xx
660+ * status code to {@link HttpException HttpExceptions}.
661+ *
662+ * @param httpClient
663+ * @param httpRequest
664+ * @return HttpResponse
665+ */
666+ public static CompletableFuture <HttpResponse <InputStream >> executeJDKAsync (HttpClient httpClient , HttpRequest httpRequest ) {
667+ return executeAsync (httpClient , httpRequest , BodyHandlers .ofInputStream ());
668+ }
669+
670+ public static <T > CompletableFuture <HttpResponse <T >> executeJDKAsync (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <T > bodyHandler ) {
671+ // This is the one place all HTTP requests go through.
672+ logRequest (httpRequest );
673+ CompletableFuture <HttpResponse <T >> future = httpClient .sendAsync (httpRequest , bodyHandler )
674+ .thenApply (httpResponse -> {
675+ logResponse (httpResponse );
676+ return httpResponse ;
677+ });
678+ return future ;
662679 }
663680
664681 /*package*/ static CompletableFuture <HttpResponse <InputStream >> asyncExecute (HttpClient httpClient , HttpRequest httpRequest ) {
0 commit comments