Author: davsclaus
Date: Fri Nov 21 10:09:17 2008
New Revision: 719662
URL: http://svn.apache.org/viewvc?rev=719662&view=rev
Log:
CAMEL-1107, CAMEL-1083, CAMEL-1095, CAMEL-1093: Major improvements to
camel-jetty and camel-http.
camel-jetty: Now properly returns fault and exception
camel-http: repsonse body is avaiable on HttpOperationFailedException
camel-jetty: introduce HttpBinding as interface and to be referenced in
Registry for end users to customize how response should be written
camel-jetty: now returns content-type and content-length if possible to
calculate
both: minor URI parsing so internal Camel options is not exposed
Added:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java
(contents, props changed)
- copied, changed from r719340,
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java
activemq/camel/trunk/components/camel-jetty/src/test/data/
activemq/camel/trunk/components/camel-jetty/src/test/data/logo.jpeg (with
props)
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyContentTypeTest.java
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpBindingRefTest.java
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpClientOptionsTest.java
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyImageFileTest.java
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java
(contents, props changed)
- copied, changed from r714221,
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyRouteTest.java
Modified:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpMessage.java
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpOperationFailedException.java
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java
activemq/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
Copied:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java
(from r719340,
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java)
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java?p2=activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java&p1=activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java&r1=719340&r2=719662&rev=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java
(original)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java
Fri Nov 21 10:09:17 2008
@@ -18,82 +18,124 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
+import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.camel.Message;
-import org.apache.camel.impl.DefaultHeaderFilterStrategy;
import org.apache.camel.spi.HeaderFilterStrategy;
/**
+ * Binding between [EMAIL PROTECTED] HttpMessage} and [EMAIL PROTECTED]
HttpServletResponse}.
+ *
* @version $Revision$
*/
-public class HttpBinding {
+public class DefaultHttpBinding implements HttpBinding {
private boolean useReaderForPayload;
private HeaderFilterStrategy headerFilterStrategy = new
HttpHeaderFilterStrategy();
- public HttpBinding(HeaderFilterStrategy headerFilterStrategy) {
+ public DefaultHttpBinding() {
+ }
+
+ public DefaultHttpBinding(HeaderFilterStrategy headerFilterStrategy) {
this.headerFilterStrategy = headerFilterStrategy;
}
- /**
- * Writes the exchange to the servlet response
- */
+ public void readRequest(HttpServletRequest request, HttpMessage message) {
+ // lets force a parse of the body and headers
+ message.getBody();
+ message.getHeaders();
+ }
+
public void writeResponse(HttpExchange exchange, HttpServletResponse
response) throws IOException {
- Message out = exchange.getOut();
- if (out != null) {
- // Set the status code in the response. Default is 200.
- if (out.getHeader(HttpProducer.HTTP_RESPONSE_CODE) != null) {
- int code = out.getHeader(HttpProducer.HTTP_RESPONSE_CODE,
Integer.class);
- response.setStatus(code);
+ if (exchange.isFailed()) {
+ Message fault = exchange.getFault(false);
+ if (fault != null) {
+ doWriteFaultResponse(fault, response);
+ } else {
+ doWriteExceptionResponse(exchange.getException(), response);
}
-
- // Write out the headers
- for (String key : out.getHeaders().keySet()) {
- String value = out.getHeader(key, String.class);
- if (headerFilterStrategy != null
- &&
!headerFilterStrategy.applyFilterToCamelHeaders(key, value)) {
- response.setHeader(key, value);
- }
+ } else {
+ Message out = exchange.getOut();
+ if (out != null) {
+ doWriteResponse(out, response);
}
+ }
+ }
- // Write out the body.
- if (out.getBody() != null) {
+ public void doWriteExceptionResponse(Throwable exception,
HttpServletResponse response) throws IOException {
+ response.setStatus(500); // 500 for internal server error
+ response.setContentType("text/plain");
+
+ // append the stacktrace as response
+ PrintWriter pw = response.getWriter();
+ exception.printStackTrace(pw);
- // Try to stream the body since that would be the most
efficient
- InputStream is = out.getBody(InputStream.class);
- if (is != null) {
- ServletOutputStream os = null;
- try {
- os = response.getOutputStream();
- int c;
- while ((c = is.read()) >= 0) {
- os.write(c);
- }
- os.flush();
- } finally {
- os.close();
- is.close();
- }
- } else {
- String data = out.getBody(String.class);
- if (data != null) {
- response.getWriter().print(data);
+ pw.flush();
+ }
+
+ public void doWriteFaultResponse(Message message, HttpServletResponse
response) throws IOException {
+ doWriteResponse(message, response);
+ }
+
+ public void doWriteResponse(Message message, HttpServletResponse response)
throws IOException {
+ // set the status code in the response. Default is 200.
+ if (message.getHeader(HttpProducer.HTTP_RESPONSE_CODE) != null) {
+ int code = message.getHeader(HttpProducer.HTTP_RESPONSE_CODE,
Integer.class);
+ response.setStatus(code);
+ }
+ // set the content type in the response.
+ if (message.getHeader("Content-Type") != null) {
+ String contentType = message.getHeader("Content-Type",
String.class);
+ response.setContentType(contentType);
+ }
+
+ // append headers
+ for (String key : message.getHeaders().keySet()) {
+ String value = message.getHeader(key, String.class);
+ if (headerFilterStrategy != null
+ && !headerFilterStrategy.applyFilterToCamelHeaders(key,
value)) {
+ response.setHeader(key, value);
+ }
+ }
+
+ // write the body.
+ if (message.getBody() != null) {
+ // try to stream the body since that would be the most efficient
+ InputStream is = message.getBody(InputStream.class);
+ int length = 0;
+ if (is != null) {
+ ServletOutputStream os = null;
+ try {
+ os = response.getOutputStream();
+ int c;
+ while ((c = is.read()) >= 0) {
+ os.write(c);
+ length++;
}
+ // set content length before we flush
+ response.setContentLength(length);
+ os.flush();
+ } finally {
+ os.close();
+ is.close();
+ }
+ } else {
+ String data = message.getBody(String.class);
+ if (data != null) {
+ // set content length before we write data
+ response.setContentLength(data.length());
+ response.getWriter().print(data);
+ response.getWriter().flush();
}
}
+
}
}
- /**
- * Parses the body from a HTTP message
- */
public Object parseBody(HttpMessage httpMessage) throws IOException {
// lets assume the body is a reader
HttpServletRequest request = httpMessage.getRequest();
@@ -108,12 +150,15 @@
return useReaderForPayload;
}
- /**
- * Should the [EMAIL PROTECTED] HttpServletRequest#getReader()} be exposed
as the payload of input messages in the Camel
- * [EMAIL PROTECTED] Message#getBody()} or not. If false then the [EMAIL
PROTECTED] HttpServletRequest#getInputStream()} will be exposed.
- */
public void setUseReaderForPayload(boolean useReaderForPayload) {
this.useReaderForPayload = useReaderForPayload;
}
+ public HeaderFilterStrategy getHeaderFilterStrategy() {
+ return headerFilterStrategy;
+ }
+
+ public void setHeaderFilterStrategy(HeaderFilterStrategy
headerFilterStrategy) {
+ this.headerFilterStrategy = headerFilterStrategy;
+ }
}
Propchange:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/DefaultHttpBinding.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java?rev=719662&view=auto
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java
(added)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpBinding.java
Fri Nov 21 10:09:17 2008
@@ -0,0 +1,97 @@
+package org.apache.camel.component.http;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.camel.Message;
+import org.apache.camel.spi.HeaderFilterStrategy;
+
+/**
+ * A plugable strategy for configuring the http binding so reading request and
writing response
+ * can be customized using the Java Servlet API.
+ * <p/>
+ * This is used by the camel-jetty.
+ *
+ * @version $Revision$
+ */
+public interface HttpBinding {
+
+ /**
+ * Startegy to read the given request and bindings it to the given message.
+ *
+ * @param request the request
+ * @param message the message to populate with data from request
+ */
+ void readRequest(HttpServletRequest request, HttpMessage message);
+
+ /**
+ * Parses the body from a [EMAIL PROTECTED]
org.apache.camel.component.http.HttpMessage}
+ *
+ * @return the parsed body returned as either a [EMAIL PROTECTED]
java.io.InputStream} or a [EMAIL PROTECTED] java.io.Reader}
+ * depending on the [EMAIL PROTECTED] #setUseReaderForPayload(boolean)}
property.
+ * @throws java.io.IOException can be thrown
+ */
+ Object parseBody(HttpMessage httpMessage) throws IOException;
+
+ /**
+ * Writes the exchange to the servlet response.
+ * <p/>
+ * Default implementation will delegate to the following methods depending
on the status of the exchange
+ * <ul>
+ * <li>doWriteResponse - processing returns a OUT message </li>
+ * <li>doWriteFaultResponse - processing returns a fault message</li>
+ * <li>doWriteResponse - processing returns an exception and status code
500</li>
+ * </ul>
+ *
+ * @param exchange the exchange
+ * @param response the http response
+ * @throws java.io.IOException can be thrown from http response
+ */
+ void writeResponse(HttpExchange exchange, HttpServletResponse response)
throws IOException;
+
+ /**
+ * Strategy method that writes the response to the http response stream
when an exception occuerd
+ *
+ * @param exception the exception occured
+ * @param response the http response
+ * @throws java.io.IOException can be thrown from http response
+ */
+ void doWriteExceptionResponse(Throwable exception, HttpServletResponse
response) throws IOException;
+
+ /**
+ * Strategy method that writes the response to the http response stream
for a fault message
+ *
+ * @param message the fault message
+ * @param response the http response
+ * @throws java.io.IOException can be thrown from http response
+ */
+ void doWriteFaultResponse(Message message, HttpServletResponse response)
throws IOException;
+
+ /**
+ * Strategy method that writes the response to the http response stream
for an OUT message
+ *
+ * @param message the OUT message
+ * @param response the http response
+ * @throws java.io.IOException can be thrown from http response
+ */
+ void doWriteResponse(Message message, HttpServletResponse response) throws
IOException;
+
+ boolean isUseReaderForPayload();
+
+ /**
+ * Should the [EMAIL PROTECTED]
javax.servlet.http.HttpServletRequest#getReader()} be exposed as the payload of
input messages in the Camel
+ * [EMAIL PROTECTED] org.apache.camel.Message#getBody()} or not. If false
then the [EMAIL PROTECTED]
javax.servlet.http.HttpServletRequest#getInputStream()} will be exposed.
+ */
+ void setUseReaderForPayload(boolean useReaderForPayload);
+
+ HeaderFilterStrategy getHeaderFilterStrategy();
+
+ /**
+ * Sets the header filter stratety to use.
+ * <p/>
+ * Will default use [EMAIL PROTECTED]
org.apache.camel.component.http.HttpHeaderFilterStrategy}
+ */
+ void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy);
+
+}
Modified:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java?rev=719662&r1=719661&r2=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
(original)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
Fri Nov 21 10:09:17 2008
@@ -24,7 +24,9 @@
import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.impl.DefaultComponent;
import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.util.CamelContextHelper;
import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.URISupport;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.params.HttpClientParams;
@@ -36,10 +38,10 @@
* @version $Revision$
*/
public class HttpComponent extends DefaultComponent implements
HeaderFilterStrategyAware {
-
- private HttpClientConfigurer httpClientConfigurer;
- private HttpConnectionManager httpConnectionManager = new
MultiThreadedHttpConnectionManager();
- private HeaderFilterStrategy headerFilterStrategy;
+ protected HttpClientConfigurer httpClientConfigurer;
+ protected HttpConnectionManager httpConnectionManager = new
MultiThreadedHttpConnectionManager();
+ protected HeaderFilterStrategy headerFilterStrategy;
+ protected HttpBinding httpBinding;
public HttpComponent() {
this.setHeaderFilterStrategy(new HttpHeaderFilterStrategy());
@@ -47,51 +49,55 @@
/**
* Connects the URL specified on the endpoint to the specified processor.
+ *
+ * @param consumer the consumer
+ * @throws Exception can be thrown
*/
public void connect(HttpConsumer consumer) throws Exception {
}
/**
- * Disconnects the URL specified on the endpoint from the specified
- * processor.
+ * Disconnects the URL specified on the endpoint from the specified
processor.
+ *
+ * @param consumer the consumer
+ * @throws Exception can be thrown
*/
public void disconnect(HttpConsumer consumer) throws Exception {
}
- public HttpClientConfigurer getHttpClientConfigurer() {
- return httpClientConfigurer;
- }
-
- public void setHttpClientConfigurer(HttpClientConfigurer
httpClientConfigurer) {
- this.httpClientConfigurer = httpClientConfigurer;
- }
-
- public HttpConnectionManager getHttpConnectionManager() {
- return httpConnectionManager;
- }
-
- public void setHttpConnectionManager(HttpConnectionManager
httpConnectionManager) {
- this.httpConnectionManager = httpConnectionManager;
- }
-
@Override
protected Endpoint createEndpoint(String uri, String remaining, Map
parameters)
throws Exception {
+
+ // http client can be configured from URI options
HttpClientParams params = new HttpClientParams();
IntrospectionSupport.setProperties(params, parameters, "httpClient.");
+ // lookup http binding in registry if provided
+ String ref = getAndRemoveParameter(parameters, "httpBindingRef",
String.class);
+ if (ref != null) {
+ httpBinding =
CamelContextHelper.mandatoryLookup(getCamelContext(), ref, HttpBinding.class);
+ }
+
+ // restructure uri to be based on the parameters left as we dont want
to include the Camel internal options
+ URI httpUri = URISupport.createRemainingURI(new URI(uri), parameters);
+ uri = httpUri.toString();
+
// validate http uri that end-user did not duplicate the http part
that can be a common error
- URI httpUri = new URI(uri);
String part = httpUri.getSchemeSpecificPart();
if (part != null) {
part = part.toLowerCase();
- if (part.startsWith("//http://") || part.startsWith("//https://"))
{
+ if (part.startsWith("//http//") || part.startsWith("//https//")) {
throw new ResolveEndpointFailedException(uri,
- "The uri part is not configured correctly. You have
duplicated the http(s) protocol.");
+ "The uri part is not configured correctly. You have
duplicated the http(s) protocol.");
}
}
- return new HttpEndpoint(uri, this, httpUri, params,
httpConnectionManager, httpClientConfigurer);
+ HttpEndpoint endpoint = new HttpEndpoint(uri, this, httpUri, params,
httpConnectionManager, httpClientConfigurer);
+ if (httpBinding != null) {
+ endpoint.setBinding(httpBinding);
+ }
+ return endpoint;
}
@Override
@@ -99,6 +105,22 @@
return false;
}
+ public HttpClientConfigurer getHttpClientConfigurer() {
+ return httpClientConfigurer;
+ }
+
+ public void setHttpClientConfigurer(HttpClientConfigurer
httpClientConfigurer) {
+ this.httpClientConfigurer = httpClientConfigurer;
+ }
+
+ public HttpConnectionManager getHttpConnectionManager() {
+ return httpConnectionManager;
+ }
+
+ public void setHttpConnectionManager(HttpConnectionManager
httpConnectionManager) {
+ this.httpConnectionManager = httpConnectionManager;
+ }
+
public HeaderFilterStrategy getHeaderFilterStrategy() {
return headerFilterStrategy;
}
@@ -106,4 +128,12 @@
public void setHeaderFilterStrategy(HeaderFilterStrategy strategy) {
headerFilterStrategy = strategy;
}
+
+ public HttpBinding getHttpBinding() {
+ return httpBinding;
+ }
+
+ public void setHttpBinding(HttpBinding httpBinding) {
+ this.httpBinding = httpBinding;
+ }
}
Modified:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java?rev=719662&r1=719661&r2=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
(original)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
Fri Nov 21 10:09:17 2008
@@ -139,7 +139,7 @@
public HttpBinding getBinding() {
if (binding == null) {
- binding = new HttpBinding(getHeaderFilterStrategy());
+ binding = new DefaultHttpBinding(getHeaderFilterStrategy());
}
return binding;
}
Modified:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpMessage.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpMessage.java?rev=719662&r1=719661&r2=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpMessage.java
(original)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpMessage.java
Fri Nov 21 10:09:17 2008
@@ -35,9 +35,9 @@
setExchange(exchange);
this.request = request;
- // lets force a parse of the body and headers
- getBody();
- getHeaders();
+ // use binding to read the request allowing end users to use their
+ // implementation of the binding
+ getExchange().getEndpoint().getBinding().readRequest(request, this);
}
@Override
Modified:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpOperationFailedException.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpOperationFailedException.java?rev=719662&r1=719661&r2=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpOperationFailedException.java
(original)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpOperationFailedException.java
Fri Nov 21 10:09:17 2008
@@ -16,6 +16,8 @@
*/
package org.apache.camel.component.http;
+import java.io.InputStream;
+
import org.apache.camel.CamelException;
import org.apache.camel.util.ObjectHelper;
import org.apache.commons.httpclient.StatusLine;
@@ -24,6 +26,7 @@
private final String redirectLocation;
private final int statusCode;
private final StatusLine statusLine;
+ private InputStream responseBody;
public HttpOperationFailedException(int statusCode, StatusLine statusLine,
String location) {
super("HTTP operation failed with statusCode: " + statusCode + ",
status: " + statusLine + (location != null ? ", redirectLocation: " + location
: ""));
@@ -56,4 +59,11 @@
return statusCode;
}
+ public InputStream getResponseBody() {
+ return responseBody;
+ }
+
+ public void setResponseBody(InputStream responseBody) {
+ this.responseBody = responseBody;
+ }
}
\ No newline at end of file
Modified:
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java?rev=719662&r1=719661&r2=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java
(original)
+++
activemq/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java
Fri Nov 21 10:09:17 2008
@@ -19,9 +19,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
@@ -42,6 +39,7 @@
import org.apache.commons.logging.LogFactory;
import static org.apache.camel.component.http.HttpMethods.HTTP_METHOD;
+
/**
* @version $Revision$
*/
@@ -98,18 +96,24 @@
}
} else {
HttpOperationFailedException exception = null;
- if (responseCode < 400 && responseCode >= 300) {
+ if (responseCode >= 300 && responseCode < 400) {
String redirectLocation;
Header locationHeader =
method.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.getValue();
exception = new
HttpOperationFailedException(responseCode, method.getStatusLine(),
redirectLocation);
+ } else {
+ // no redirect location
+ exception = new
HttpOperationFailedException(responseCode, method.getStatusLine());
}
} else {
+ // internal server error (error code 500)
exception = new HttpOperationFailedException(responseCode,
method.getStatusLine());
}
if (exception != null) {
+ // set also the response body as well
+ exception.setResponseBody(extractResponseBody(method));
throw exception;
}
}
@@ -119,14 +123,6 @@
}
}
- public HttpClient getHttpClient() {
- return httpClient;
- }
-
- public void setHttpClient(HttpClient httpClient) {
- this.httpClient = httpClient;
- }
-
/**
* Strategy when executing the method (calling the remote server).
*
@@ -138,12 +134,23 @@
return httpClient.executeMethod(method);
}
+ /**
+ * Extracts the response from the method as a InputStream.
+ *
+ * @param method the method that was executed
+ * @return the response as a stream
+ * @throws IOException can be thrown
+ */
protected static InputStream extractResponseBody(HttpMethod method) throws
IOException {
LoadingByteArrayOutputStream bos = null;
InputStream is = null;
try {
bos = new LoadingByteArrayOutputStream();
is = method.getResponseBodyAsStream();
+ // in case of no response stream
+ if (is == null) {
+ return null;
+ }
IOUtils.copy(is, bos);
bos.flush();
return bos.createInputStream();
@@ -153,6 +160,12 @@
}
}
+ /**
+ * Creates the HttpMethod to use to call the remote server, either its GET
or POST.
+ *
+ * @param exchange the exchange
+ * @return the created method as either GET or POST
+ */
protected HttpMethod createMethod(Exchange exchange) {
// is a query string provided in the endpoint URI or in a header
(header overrules endpoint)
String queryString = exchange.getIn().getHeader(QUERY, String.class);
@@ -179,7 +192,7 @@
if (uri == null) {
uri = ((HttpEndpoint)getEndpoint()).getHttpUri().toString();
}
-
+
HttpMethod method = methodToUse.createMethod(uri);
if (queryString != null) {
@@ -192,6 +205,12 @@
return method;
}
+ /**
+ * Creates a holder object for the data to send to the remote server.
+ *
+ * @param exchange the exchange with the IN message with data to send
+ * @return the data holder
+ */
protected RequestEntity createRequestEntity(Exchange exchange) {
Message in = exchange.getIn();
if (in.getBody() == null) {
@@ -215,4 +234,12 @@
}
}
}
+
+ public HttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ public void setHttpClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
}
Modified:
activemq/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java?rev=719662&r1=719661&r2=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
(original)
+++
activemq/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
Fri Nov 21 10:09:17 2008
@@ -22,9 +22,13 @@
import org.apache.camel.Endpoint;
import org.apache.camel.component.http.CamelServlet;
+import org.apache.camel.component.http.HttpBinding;
import org.apache.camel.component.http.HttpComponent;
import org.apache.camel.component.http.HttpConsumer;
import org.apache.camel.component.http.HttpEndpoint;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.URISupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mortbay.jetty.Connector;
@@ -65,20 +69,40 @@
}
}
- private static final Log LOGGER =
LogFactory.getLog(JettyHttpComponent.class);
+ private static final transient Log LOG =
LogFactory.getLog(JettyHttpComponent.class);
- private Server server;
- private HashMap<String, ConnectorRef> connectors = new HashMap<String,
ConnectorRef>();
- private HttpClient httpClient;
- private String sslKeyPassword;
- private String sslPassword;
- private String sslKeystore;
- private SslSocketConnector sslSocketConnector;
+ protected Server server;
+ protected HashMap<String, ConnectorRef> connectors = new HashMap<String,
ConnectorRef>();
+ protected HttpClient httpClient;
+ protected String sslKeyPassword;
+ protected String sslPassword;
+ protected String sslKeystore;
+ protected SslSocketConnector sslSocketConnector;
@Override
protected Endpoint createEndpoint(String uri, String remaining, Map
parameters) throws Exception {
- URI httpURL = uri.startsWith("jetty:") ? new URI(remaining) : new
URI(uri);
- JettyHttpEndpoint result = new JettyHttpEndpoint(this, uri, httpURL,
getHttpConnectionManager());
+ uri = uri.startsWith("jetty:") ? remaining : uri;
+
+ // http client can be configured from URI options
+ if (httpClient == null) {
+ httpClient = createHttpClient();
+ }
+ IntrospectionSupport.setProperties(httpClient, parameters,
"httpClient.");
+
+ // lookup http binding in registry if provided
+ String ref = getAndRemoveParameter(parameters, "httpBindingRef",
String.class);
+ if (ref != null) {
+ httpBinding =
CamelContextHelper.mandatoryLookup(getCamelContext(), ref, HttpBinding.class);
+ }
+
+ // restructure uri to be based on the parameters left as we dont want
to include the Camel internal options
+ URI httpUri = URISupport.createRemainingURI(new URI(uri), parameters);
+ uri = httpUri.toString();
+
+ JettyHttpEndpoint result = new JettyHttpEndpoint(this, uri, httpUri,
getHttpConnectionManager());
+ if (httpBinding != null) {
+ result.setBinding(httpBinding);
+ }
setProperties(result, parameters);
return result;
}
@@ -90,7 +114,6 @@
*/
@Override
public void connect(HttpConsumer consumer) throws Exception {
-
// Make sure that there is a connector for the requested endpoint.
JettyHttpEndpoint endpoint = (JettyHttpEndpoint)consumer.getEndpoint();
String connectorKey = endpoint.getProtocol() + ":" +
endpoint.getHttpUri().getHost() + ":" + endpoint.getPort();
@@ -107,7 +130,7 @@
connector.setPort(endpoint.getPort());
connector.setHost(endpoint.getHttpUri().getHost());
if
("localhost".equalsIgnoreCase(endpoint.getHttpUri().getHost())) {
- LOGGER.warn("You use localhost interface! It means that no
external connections will be available. Don't you want to use 0.0.0.0 instead
(all network interfaces)?");
+ LOG.warn("You use localhost interface! It means that no
external connections will be available. Don't you want to use 0.0.0.0 instead
(all network interfaces)?");
}
getServer().addConnector(connector);
Added: activemq/camel/trunk/components/camel-jetty/src/test/data/logo.jpeg
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/test/data/logo.jpeg?rev=719662&view=auto
==============================================================================
Binary file - no diff available.
Propchange: activemq/camel/trunk/components/camel-jetty/src/test/data/logo.jpeg
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyContentTypeTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyContentTypeTest.java?rev=719662&view=auto
==============================================================================
---
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyContentTypeTest.java
(added)
+++
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyContentTypeTest.java
Fri Nov 21 10:09:17 2008
@@ -0,0 +1,75 @@
+/**
+ * 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.jetty;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Unit test for content-type
+ */
+public class JettyContentTypeTest extends ContextTestSupport {
+
+ public void testSameContentType() throws Exception {
+ Endpoint endpoint =
context.getEndpoint("http://localhost:8080/myapp/myservice");
+ Exchange exchange = endpoint.createExchange();
+ exchange.getIn().setBody("<order>123</order>");
+ exchange.getIn().setHeader("user", "Claus");
+ exchange.getIn().setHeader("content-type", "text/xml");
+ template.send(endpoint, exchange);
+
+ String body = exchange.getOut().getBody(String.class);
+ assertEquals("<order>OK</order>", body);
+ assertOutMessageHeader(exchange, "content-type", "text/xml");
+ }
+
+ public void testMixedContentType() throws Exception {
+ Endpoint endpoint =
context.getEndpoint("http://localhost:8080/myapp/myservice");
+ Exchange exchange = endpoint.createExchange();
+ exchange.getIn().setBody("<order>123</order>");
+ exchange.getIn().setHeader("Content-Type", "text/xml");
+ template.send(endpoint, exchange);
+
+ String body = exchange.getOut().getBody(String.class);
+ assertEquals("FAIL", body);
+ assertOutMessageHeader(exchange, "Content-Type", "text/plain");
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ public void configure() throws Exception {
+
from("jetty:http://localhost:8080/myapp/myservice").process(new
MyBookService());
+ }
+ };
+ }
+
+ public class MyBookService implements Processor {
+ public void process(Exchange exchange) throws Exception {
+ if (exchange.getIn().getHeader("user") != null) {
+ exchange.getOut().setBody("<order>OK</order>");
+ } else {
+ exchange.getOut().setBody("FAIL");
+ exchange.getOut().setHeader("Content-Type", "text/plain");
+ }
+ }
+ }
+
+}
\ No newline at end of file
Added:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpBindingRefTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpBindingRefTest.java?rev=719662&view=auto
==============================================================================
---
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpBindingRefTest.java
(added)
+++
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpBindingRefTest.java
Fri Nov 21 10:09:17 2008
@@ -0,0 +1,71 @@
+package org.apache.camel.component.jetty;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.http.DefaultHttpBinding;
+import org.apache.camel.impl.JndiRegistry;
+
+/**
+ * Unit test for http binding ref option.
+ */
+public class JettyHttpBindingRefTest extends ContextTestSupport {
+
+ public void testDefaultHttpBinding() throws Exception {
+ Object out =
template.requestBody("http://localhost:8080/myapp/myservice", "Hello World");
+ assertEquals("Bye World",
context.getTypeConverter().convertTo(String.class, out));
+ }
+
+ public void testCustomHttpBinding() throws Exception {
+ Object out =
template.requestBody("http://localhost:8081/myapp/myotherservice", "Hello
World");
+ assertEquals("Something went wrong but we dont care",
context.getTypeConverter().convertTo(String.class, out));
+ }
+
+ @Override
+ protected JndiRegistry createRegistry() throws Exception {
+ JndiRegistry jndi = super.createRegistry();
+ jndi.bind("default", new DefaultHttpBinding());
+ jndi.bind("myownbinder", new MyHttpBinding());
+ return jndi;
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ errorHandler(noErrorHandler());
+
+
from("jetty:http://localhost:8080/myapp/myservice?httpBindingRef=default").transform().constant("Bye
World");
+
+
from("jetty:http://localhost:8081/myapp/myotherservice?httpBindingRef=myownbinder").process(new
Processor() {
+ public void process(Exchange exchange) throws Exception {
+ throw new IllegalStateException("Not implemented");
+ }
+ });
+ }
+ };
+ }
+
+ // START SNIPPET: e1
+ public class MyHttpBinding extends DefaultHttpBinding {
+
+ @Override
+ public void doWriteExceptionResponse(Throwable exception,
HttpServletResponse response) throws IOException {
+ // we override the doWriteExceptionResponse as we only want to
alter the binding how exceptions is
+ // written back to the client.
+
+ // we just return HTTP 200 so the client thinks its okay
+ response.setStatus(200);
+ // and we return this fixed text
+ response.getWriter().write("Something went wrong but we dont
care");
+ }
+ }
+ // END SNIPPET: e1
+
+}
+
Added:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpClientOptionsTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpClientOptionsTest.java?rev=719662&view=auto
==============================================================================
---
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpClientOptionsTest.java
(added)
+++
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyHttpClientOptionsTest.java
Fri Nov 21 10:09:17 2008
@@ -0,0 +1,32 @@
+package org.apache.camel.component.jetty;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Unit test for http client options.
+ */
+public class JettyHttpClientOptionsTest extends ContextTestSupport {
+
+ public void testCustomHttpBinding() throws Exception {
+ // assert jetty was configured with our timeout
+ JettyHttpComponent jetty = context.getComponent("jetty",
JettyHttpComponent.class);
+ assertNotNull(jetty);
+ assertEquals(5555, jetty.getHttpClient().getIdleTimeout());
+
+ // send and receive
+ Object out =
template.requestBody("http://localhost:8080/myapp/myservice", "Hello World");
+ assertEquals("Bye World",
context.getTypeConverter().convertTo(String.class, out));
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("jetty:http://localhost:8080/myapp/myservice?httpClient.idleTimeout=5555").transform().constant("Bye
World");
+ }
+ };
+ }
+
+}
\ No newline at end of file
Added:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyImageFileTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyImageFileTest.java?rev=719662&view=auto
==============================================================================
---
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyImageFileTest.java
(added)
+++
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyImageFileTest.java
Fri Nov 21 10:09:17 2008
@@ -0,0 +1,57 @@
+/**
+ * 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.jetty;
+
+import java.io.File;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Unit test for exposing a http server that returns images
+ */
+public class JettyImageFileTest extends ContextTestSupport {
+
+ public void testImageContentType() throws Exception {
+ Endpoint endpoint =
context.getEndpoint("http://localhost:8080/myapp/myservice");
+ Exchange exchange = endpoint.createExchange();
+ template.send(endpoint, exchange);
+
+ assertNotNull(exchange.getOut().getBody());
+ assertOutMessageHeader(exchange, "Content-Type", "image/jpeg");
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ public void configure() throws Exception {
+
from("jetty:http://localhost:8080/myapp/myservice").process(new
MyImageService());
+ }
+ };
+ }
+
+ public class MyImageService implements Processor {
+ public void process(Exchange exchange) throws Exception {
+ exchange.getOut().setBody(new File("src/test/data/logo.jpeg"));
+ exchange.getOut().setHeader("Content-Type", "image/jpeg");
+ }
+ }
+
+}
\ No newline at end of file
Copied:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java
(from r714221,
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyRouteTest.java)
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java?p2=activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java&p1=activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyRouteTest.java&r1=714221&r2=719662&rev=719662&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyRouteTest.java
(original)
+++
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java
Fri Nov 21 10:09:17 2008
@@ -16,53 +16,45 @@
*/
package org.apache.camel.component.jetty;
-import javax.servlet.http.HttpServletRequest;
-
import org.apache.camel.ContextTestSupport;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.http.HttpOperationFailedException;
/**
- * Unit test for wiki demonstration.
+ * Unit test for HttpOperationFailedException should contain reponse body
*/
-public class JettyRouteTest extends ContextTestSupport {
+public class JettyResponseBodyWhenErrorTest extends ContextTestSupport {
- public void testSendToJetty() throws Exception {
- Object response =
template.requestBody("http://localhost:8080/myapp/myservice", "bookid=123");
- // convert the response to a String
- String body = context.getTypeConverter().convertTo(String.class,
response);
- assertEquals("<html><body>Book 123 is Camel in Action</body></html>",
body);
+ public void testResponseBodyWhenError() throws Exception {
+ try {
+ template.sendBody("http://localhost:8080/myapp/myservice",
"bookid=123");
+ fail("Should have thrown an exception");
+ } catch (RuntimeCamelException e) {
+ HttpOperationFailedException cause =
(HttpOperationFailedException) e.getCause();
+ assertEquals(500, cause.getStatusCode());
+ String body = context.getTypeConverter().convertTo(String.class,
cause.getResponseBody());
+ assertTrue(body.indexOf("Damm") > -1);
+ assertTrue(body.indexOf("IllegalArgumentException") > -1);
+ }
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
public void configure() throws Exception {
- // START SNIPPET: e1
+ errorHandler(noErrorHandler());
from("jetty:http://localhost:8080/myapp/myservice").process(new
MyBookService());
- // END SNIPPET: e1
}
};
}
- // START SNIPPET: e2
public class MyBookService implements Processor {
public void process(Exchange exchange) throws Exception {
- // just get the body as a string
- String body = exchange.getIn().getBody(String.class);
-
- // we have access to the HttpServletRequest here and we can grab
it if we need it
- HttpServletRequest req =
exchange.getIn().getBody(HttpServletRequest.class);
- assertNotNull(req);
-
- // for unit testing
- assertEquals("bookid=123", body);
-
- // send a html response
- exchange.getOut(true).setBody("<html><body>Book 123 is Camel in
Action</body></html>");
+ throw new IllegalArgumentException("Damm");
}
}
- // END SNIPPET: e2
-}
+}
\ No newline at end of file
Propchange:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange:
activemq/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyResponseBodyWhenErrorTest.java
------------------------------------------------------------------------------
svn:mergeinfo =