001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015 ForgeRock AS. 015 */ 016 017package org.forgerock.http.apache.async; 018 019import static java.lang.String.format; 020 021import java.io.IOException; 022 023import org.apache.http.HttpResponse; 024import org.apache.http.client.methods.HttpUriRequest; 025import org.apache.http.concurrent.FutureCallback; 026import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; 027import org.forgerock.http.apache.AbstractHttpClient; 028import org.forgerock.http.io.Buffer; 029import org.forgerock.http.protocol.Request; 030import org.forgerock.http.protocol.Response; 031import org.forgerock.http.protocol.Status; 032import org.forgerock.util.Factory; 033import org.forgerock.util.promise.NeverThrowsException; 034import org.forgerock.util.promise.Promise; 035import org.forgerock.util.promise.PromiseImpl; 036 037/** 038 * Apache HTTP Async Client based implementation. 039 */ 040public class AsyncHttpClient extends AbstractHttpClient { 041 042 private final CloseableHttpAsyncClient client; 043 044 AsyncHttpClient(final CloseableHttpAsyncClient client, final Factory<Buffer> storage) { 045 super(storage); 046 // Client should already be started 047 this.client = client; 048 } 049 050 @Override 051 public Promise<Response, NeverThrowsException> sendAsync(final Request request) { 052 053 HttpUriRequest clientRequest = createHttpUriRequest(request); 054 055 // Send request and return the configured Promise 056 final PromiseImpl<Response, NeverThrowsException> promise = PromiseImpl.create(); 057 client.execute(clientRequest, new FutureCallback<HttpResponse>() { 058 059 @Override 060 public void completed(final HttpResponse result) { 061 Response response = createResponse(result); 062 promise.handleResult(response); 063 } 064 065 @Override 066 public void failed(final Exception ex) { 067 Response response = new Response(Status.BAD_GATEWAY); 068 response.setEntity(format("Failed to obtain response for %s", request.getUri())); 069 response.setCause(ex); 070 promise.handleResult(response); 071 } 072 073 @Override 074 public void cancelled() { 075 failed(new InterruptedException("Request processing has been cancelled")); 076 } 077 }); 078 079 return promise; 080 } 081 082 @Override 083 public void close() throws IOException { 084 client.close(); 085 } 086}