/**
* 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.
*/
package org.apache.camel.component.ahc;
import java.io.ByteArrayOutputStream;
import org.apache.camel.AsyncCallback;
import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultAsyncProducer;
import org.asynchttpclient.AsyncHandler;
import org.asynchttpclient.AsyncHttpClient;
import org.asynchttpclient.HttpResponseBodyPart;
import org.asynchttpclient.HttpResponseHeaders;
import org.asynchttpclient.HttpResponseStatus;
import org.asynchttpclient.Request;
/**
*
*/
public class AhcProducer extends DefaultAsyncProducer {
private final AsyncHttpClient client;
public AhcProducer(AhcEndpoint endpoint) {
super(endpoint);
this.client = endpoint.getClient();
}
@Override
public AhcEndpoint getEndpoint() {
return (AhcEndpoint) super.getEndpoint();
}
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
try {
// AHC supports async processing
Request request = getEndpoint().getBinding().prepareRequest(getEndpoint(), exchange);
log.debug("Executing request {} ", request);
client.prepareRequest(request).execute(new AhcAsyncHandler(exchange, callback, request.getUrl(), getEndpoint().getBufferSize()));
return false;
} catch (Exception e) {
exchange.setException(e);
callback.done(true);
return true;
}
}
/**
* Camel {@link AsyncHandler} to receive callbacks during the processing of the request.
*/
private final class AhcAsyncHandler implements AsyncHandler<Exchange> {
private final Exchange exchange;
private final AsyncCallback callback;
private final String url;
private final ByteArrayOutputStream os;
private int contentLength;
private int statusCode;
private String statusText;
private AhcAsyncHandler(Exchange exchange, AsyncCallback callback, String url, int bufferSize) {
this.exchange = exchange;
this.callback = callback;
this.url = url;
this.os = new ByteArrayOutputStream(bufferSize);
}
@Override
public void onThrowable(Throwable t) {
if (log.isTraceEnabled()) {
log.trace("{} onThrowable {}", exchange.getExchangeId(), t);
}
try {
getEndpoint().getBinding().onThrowable(getEndpoint(), exchange, t);
} catch (Exception e) {
exchange.setException(e);
} finally {
callback.done(false);
}
}
@Override
public Exchange onCompleted() throws Exception {
if (log.isTraceEnabled()) {
log.trace("{} onCompleted", exchange.getExchangeId());
}
try {
getEndpoint().getBinding().onComplete(getEndpoint(), exchange, url, os, contentLength, statusCode, statusText);
} catch (Exception e) {
exchange.setException(e);
} finally {
// signal we are done
callback.done(false);
}
return exchange;
}
@Override
public String toString() {
return "AhcAsyncHandler for exchangeId: " + exchange.getExchangeId() + " -> " + url;
}
@Override
public State onBodyPartReceived(HttpResponseBodyPart bodyPart)
throws Exception {
// write body parts to stream, which we will bind to the Camel Exchange in onComplete
os.write(bodyPart.getBodyPartBytes());
if (log.isTraceEnabled()) {
log.trace("{} onBodyPartReceived {} bytes", exchange.getExchangeId(), bodyPart.length());
}
contentLength += bodyPart.length();
return State.CONTINUE;
}
@Override
public State onStatusReceived(HttpResponseStatus responseStatus)
throws Exception {
if (log.isTraceEnabled()) {
log.trace("{} onStatusReceived {}", exchange.getExchangeId(), responseStatus);
}
try {
statusCode = responseStatus.getStatusCode();
statusText = responseStatus.getStatusText();
getEndpoint().getBinding().onStatusReceived(getEndpoint(), exchange, responseStatus);
} catch (Exception e) {
exchange.setException(e);
}
return State.CONTINUE;
}
@Override
public State onHeadersReceived(HttpResponseHeaders headers) throws Exception {
if (log.isTraceEnabled()) {
log.trace("{} onHeadersReceived {}", exchange.getExchangeId(), headers);
}
try {
getEndpoint().getBinding().onHeadersReceived(getEndpoint(), exchange, headers);
} catch (Exception e) {
exchange.setException(e);
}
return State.CONTINUE;
}
}
}