001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.component.ahc;
018
019 import java.io.ByteArrayOutputStream;
020
021 import com.ning.http.client.AsyncHandler;
022 import com.ning.http.client.AsyncHttpClient;
023 import com.ning.http.client.HttpResponseBodyPart;
024 import com.ning.http.client.HttpResponseHeaders;
025 import com.ning.http.client.HttpResponseStatus;
026 import com.ning.http.client.Request;
027 import org.apache.camel.AsyncCallback;
028 import org.apache.camel.Exchange;
029 import org.apache.camel.impl.DefaultAsyncProducer;
030
031 /**
032 *
033 */
034 public class AhcProducer extends DefaultAsyncProducer {
035
036 private final AsyncHttpClient client;
037
038 public AhcProducer(AhcEndpoint endpoint) {
039 super(endpoint);
040 this.client = endpoint.getClient();
041 }
042
043 @Override
044 public AhcEndpoint getEndpoint() {
045 return (AhcEndpoint) super.getEndpoint();
046 }
047
048 @Override
049 @SuppressWarnings("unchecked")
050 public boolean process(Exchange exchange, AsyncCallback callback) {
051 try {
052 // AHC supports async processing
053 Request request = getEndpoint().getBinding().prepareRequest(getEndpoint(), exchange);
054 log.debug("Executing request {} ", request);
055 client.prepareRequest(request).execute(new AhcAsyncHandler(exchange, callback, request.getUrl()));
056 return false;
057 } catch (Exception e) {
058 exchange.setException(e);
059 callback.done(true);
060 return true;
061 }
062 }
063
064 /**
065 * Camel {@link AsyncHandler} to receive callbacks during the processing of the request.
066 */
067 private final class AhcAsyncHandler implements AsyncHandler<Exchange> {
068
069 private final Exchange exchange;
070 private final AsyncCallback callback;
071 private final String url;
072 private final ByteArrayOutputStream os;
073 private int contentLength;
074 private int statusCode;
075 private String statusText;
076
077 private AhcAsyncHandler(Exchange exchange, AsyncCallback callback, String url) {
078 this.exchange = exchange;
079 this.callback = callback;
080 this.url = url;
081 this.os = new ByteArrayOutputStream();
082 }
083
084 @Override
085 public void onThrowable(Throwable t) {
086 log.trace("{} onThrowable {}", exchange.getExchangeId(), t);
087 try {
088 getEndpoint().getBinding().onThrowable(getEndpoint(), exchange, t);
089 } catch (Exception e) {
090 exchange.setException(e);
091 }
092 callback.done(false);
093 }
094
095 @Override
096 public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
097 // write body parts to stream, which we will bind to the Camel Exchange in onComplete
098 int wrote = bodyPart.writeTo(os);
099 log.trace("{} onBodyPartReceived {} bytes", exchange.getExchangeId(), wrote);
100 contentLength += wrote;
101 return STATE.CONTINUE;
102 }
103
104 @Override
105 public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
106 log.trace("{} onStatusReceived {}", exchange.getExchangeId(), responseStatus);
107 try {
108 statusCode = responseStatus.getStatusCode();
109 statusText = responseStatus.getStatusText();
110 getEndpoint().getBinding().onStatusReceived(getEndpoint(), exchange, responseStatus);
111 } catch (Exception e) {
112 exchange.setException(e);
113 }
114 return STATE.CONTINUE;
115 }
116
117 @Override
118 public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
119 log.trace("{} onHeadersReceived {}", exchange.getExchangeId(), headers);
120 try {
121 getEndpoint().getBinding().onHeadersReceived(getEndpoint(), exchange, headers);
122 } catch (Exception e) {
123 exchange.setException(e);
124 }
125 return STATE.CONTINUE;
126 }
127
128 @Override
129 public Exchange onCompleted() throws Exception {
130 log.trace("{} onCompleted", exchange.getExchangeId());
131 try {
132 getEndpoint().getBinding().onComplete(getEndpoint(), exchange, url, os, contentLength, statusCode, statusText);
133 } catch (Exception e) {
134 exchange.setException(e);
135 } finally {
136 // signal we are done
137 callback.done(false);
138 }
139 return exchange;
140 }
141
142 @Override
143 public String toString() {
144 return "AhcAsyncHandler for exchangeId: " + exchange.getExchangeId() + " -> " + url;
145 }
146 }
147
148 }