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.jetty;
018
019 import java.io.IOException;
020 import java.io.InputStream;
021 import java.net.URI;
022 import java.net.URISyntaxException;
023 import java.util.Map;
024
025 import org.apache.camel.AsyncCallback;
026 import org.apache.camel.AsyncProcessor;
027 import org.apache.camel.Endpoint;
028 import org.apache.camel.Exchange;
029 import org.apache.camel.Message;
030 import org.apache.camel.component.http.HttpMethods;
031 import org.apache.camel.component.http.helper.HttpProducerHelper;
032 import org.apache.camel.impl.DefaultProducer;
033 import org.apache.camel.spi.HeaderFilterStrategy;
034 import org.apache.camel.util.AsyncProcessorHelper;
035 import org.apache.camel.util.ExchangeHelper;
036 import org.apache.camel.util.ObjectHelper;
037 import org.apache.camel.util.URISupport;
038 import org.apache.commons.logging.Log;
039 import org.apache.commons.logging.LogFactory;
040 import org.eclipse.jetty.client.HttpClient;
041 import org.eclipse.jetty.io.ByteArrayBuffer;
042
043 /**
044 * @version $Revision: 19997 $
045 */
046 public class JettyHttpProducer extends DefaultProducer implements AsyncProcessor {
047 private static final transient Log LOG = LogFactory.getLog(JettyHttpProducer.class);
048 private final HttpClient client;
049 private JettyHttpBinding binding;
050
051 public JettyHttpProducer(Endpoint endpoint, HttpClient client) {
052 super(endpoint);
053 this.client = client;
054 }
055
056 @Override
057 public JettyHttpEndpoint getEndpoint() {
058 return (JettyHttpEndpoint) super.getEndpoint();
059 }
060
061 public void process(Exchange exchange) throws Exception {
062 AsyncProcessorHelper.process(this, exchange);
063 }
064
065 public boolean process(Exchange exchange, final AsyncCallback callback) {
066 HttpClient client = getEndpoint().getClient();
067
068 try {
069 JettyContentExchange httpExchange = createHttpExchange(exchange, callback);
070 doSendExchange(client, httpExchange);
071 } catch (Exception e) {
072 // error occurred before we had a chance to go async
073 // so set exception and invoke callback true
074 exchange.setException(e);
075 callback.done(true);
076 return true;
077 }
078
079 // we should continue processing this asynchronously
080 return false;
081 }
082
083 protected JettyContentExchange createHttpExchange(Exchange exchange, AsyncCallback callback) throws Exception {
084 String url = HttpProducerHelper.createURL(exchange, getEndpoint());
085 HttpMethods methodToUse = HttpProducerHelper.createMethod(exchange, getEndpoint(), exchange.getIn().getBody() != null);
086 String method = methodToUse.createMethod(url).getName();
087
088 JettyContentExchange httpExchange = new JettyContentExchange(exchange, getBinding(), client);
089 httpExchange.setMethod(method);
090 httpExchange.setURL(url);
091
092 // set query parameters
093 doSetQueryParameters(exchange, httpExchange);
094
095 // if we post then set data
096 if (HttpMethods.POST.equals(methodToUse)) {
097
098 String contentType = ExchangeHelper.getContentType(exchange);
099 if (contentType != null) {
100 httpExchange.setRequestContentType(contentType);
101 }
102
103 // try with String at first
104 String data = exchange.getIn().getBody(String.class);
105 if (data != null) {
106 String charset = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
107 if (charset != null) {
108 httpExchange.setRequestContent(new ByteArrayBuffer(data, charset));
109 } else {
110 httpExchange.setRequestContent(new ByteArrayBuffer(data));
111 }
112 } else {
113 // then fallback to input stream
114 InputStream is = exchange.getContext().getTypeConverter().mandatoryConvertTo(InputStream.class, exchange, exchange.getIn().getBody());
115 httpExchange.setRequestContentSource(is);
116 }
117 }
118
119 // and copy headers from IN message
120 Message in = exchange.getIn();
121 HeaderFilterStrategy strategy = getEndpoint().getHeaderFilterStrategy();
122
123 // propagate headers as HTTP headers
124 for (String headerName : in.getHeaders().keySet()) {
125 String headerValue = in.getHeader(headerName, String.class);
126 if (strategy != null && !strategy.applyFilterToCamelHeaders(headerName, headerValue, exchange)) {
127 httpExchange.addRequestHeader(headerName, headerValue);
128 }
129 }
130
131 // set the callback, which will handle all the response logic
132 httpExchange.setCallback(callback);
133 return httpExchange;
134 }
135
136 @SuppressWarnings("unchecked")
137 private void doSetQueryParameters(Exchange exchange, JettyContentExchange httpExchange) throws URISyntaxException {
138 // is a query string provided in the endpoint URI or in a header (header
139 // overrules endpoint)
140 String queryString = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);
141 if (queryString == null) {
142 queryString = getEndpoint().getHttpUri().getQuery();
143 }
144
145 if (ObjectHelper.isEmpty(queryString)) {
146 return;
147 }
148
149 // okay we need to add the query string to the URI so we need to juggle a bit with the parameters
150 String uri = httpExchange.getURI();
151
152 Map parameters = URISupport.parseParameters(new URI(uri));
153 parameters.putAll(URISupport.parseQuery(queryString));
154
155 if (uri.contains("?")) {
156 uri = ObjectHelper.before(uri, "?");
157 }
158 if (!parameters.isEmpty()) {
159 uri = uri + "?" + URISupport.createQueryString(parameters);
160 httpExchange.setURI(uri);
161 }
162 }
163
164 protected static void doSendExchange(HttpClient client, JettyContentExchange httpExchange) throws IOException {
165 if (LOG.isDebugEnabled()) {
166 LOG.debug("Sending HTTP request to: " + httpExchange.getUrl());
167 }
168 client.send(httpExchange);
169 }
170
171 public JettyHttpBinding getBinding() {
172 return binding;
173 }
174
175 public void setBinding(JettyHttpBinding binding) {
176 this.binding = binding;
177 }
178
179 @Override
180 protected void doStart() throws Exception {
181 client.start();
182 super.doStart();
183 }
184
185 @Override
186 protected void doStop() throws Exception {
187 super.doStop();
188 client.stop();
189 }
190 }