Author: hadrian Date: Tue Nov 30 23:20:18 2010 New Revision: 1040823 URL: http://svn.apache.org/viewvc?rev=1040823&view=rev Log: CAMEL-3379. Patch applied with thanks to Paul
Added: camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/MultiPartFormTestWithCustomFilter.java Modified: camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelMultipartFilter.java camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java camel/trunk/components/camel-jetty/src/test/resources/log4j.properties Modified: camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelMultipartFilter.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelMultipartFilter.java?rev=1040823&r1=1040822&r2=1040823&view=diff ============================================================================== --- camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelMultipartFilter.java (original) +++ camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelMultipartFilter.java Tue Nov 30 23:20:18 2010 @@ -18,26 +18,39 @@ package org.apache.camel.component.jetty import java.io.IOException; +import javax.servlet.Filter; import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; -import org.eclipse.jetty.servlets.MultiPartFilter; - /** * A multipart filter that processes only initially dispatched requests. * Re-dispatched requests are ignored. */ -class CamelMultipartFilter extends MultiPartFilter { - - @Override +class CamelMultipartFilter implements Filter { + + private Filter wrapped; + + public CamelMultipartFilter(Filter wrapped) { + this.wrapped = wrapped; + } + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (request.getAttribute(CamelContinuationServlet.EXCHANGE_ATTRIBUTE_NAME) == null) { - super.doFilter(request, response, chain); + wrapped.doFilter(request, response, chain); } else { chain.doFilter(request, response); } } + public void destroy() { + wrapped.destroy(); + } + + public void init(FilterConfig config) throws ServletException { + wrapped.init(config); + } + } Modified: camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java?rev=1040823&r1=1040822&r2=1040823&view=diff ============================================================================== --- camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java (original) +++ camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java Tue Nov 30 23:20:18 2010 @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import javax.management.MBeanServer; +import javax.servlet.Filter; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; @@ -55,6 +56,7 @@ import org.eclipse.jetty.server.ssl.SslS import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.servlets.MultiPartFilter; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ThreadPool; @@ -132,6 +134,7 @@ public class JettyHttpComponent extends Boolean enableJmx = getAndRemoveParameter(parameters, "enableJmx", Boolean.class); Boolean enableMultipartFilter = getAndRemoveParameter(parameters, "enableMultipartFilter", Boolean.class, true); + Filter multipartFilter = resolveAndRemoveReferenceParameter(parameters, "multipartFilterRef", Filter.class); // configure http client if we have url configuration for it // http client is only used for jetty http producer (hence not very commonly used) @@ -190,6 +193,11 @@ public class JettyHttpComponent extends } endpoint.setEnableMultipartFilter(enableMultipartFilter); + + if (multipartFilter != null) { + endpoint.setMultipartFilter(multipartFilter); + endpoint.setEnableMultipartFilter(true); + } setProperties(endpoint, parameters); return endpoint; @@ -288,8 +296,13 @@ public class JettyHttpComponent extends } context.setAttribute("javax.servlet.context.tempdir", file); } - filterHolder.setFilter(new CamelMultipartFilter()); - // add the default MultiPartFilter filter for it + // if a filter ref was provided, use it. + Filter filter = ((JettyHttpEndpoint) endpoint).getMultipartFilter(); + if (filter == null) { + // if no filter ref was provided, use the default filter + filter = new MultiPartFilter(); + } + filterHolder.setFilter(new CamelMultipartFilter(filter)); String pathSpec = endpoint.getPath(); if (pathSpec == null || "".equals(pathSpec)) { pathSpec = "/"; @@ -298,6 +311,7 @@ public class JettyHttpComponent extends pathSpec = pathSpec.endsWith("/") ? pathSpec + "*" : pathSpec + "/*"; } context.addFilter(filterHolder, pathSpec, 0); + LOG.debug("using multipart filter implementation "+filter.getClass().getName() +" for path "+pathSpec); } /** Modified: camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java?rev=1040823&r1=1040822&r2=1040823&view=diff ============================================================================== --- camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java (original) +++ camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java Tue Nov 30 23:20:18 2010 @@ -20,6 +20,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.List; +import javax.servlet.Filter; + import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; @@ -40,6 +42,7 @@ public class JettyHttpEndpoint extends H private JettyHttpBinding jettyBinding; private boolean enableJmx; private boolean enableMultipartFilter; + private Filter multipartFilter; public JettyHttpEndpoint(JettyHttpComponent component, String uri, URI httpURL) throws URISyntaxException { super(uri, component, httpURL); @@ -120,5 +123,13 @@ public class JettyHttpEndpoint extends H public void setEnableMultipartFilter(boolean enableMultipartFilter) { this.enableMultipartFilter = enableMultipartFilter; - } + } + + public void setMultipartFilter(Filter filter) { + this.multipartFilter = filter; + } + + public Filter getMultipartFilter() { + return multipartFilter; + } } Added: camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/MultiPartFormTestWithCustomFilter.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/MultiPartFormTestWithCustomFilter.java?rev=1040823&view=auto ============================================================================== --- camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/MultiPartFormTestWithCustomFilter.java (added) +++ camel/trunk/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/MultiPartFormTestWithCustomFilter.java Tue Nov 30 23:20:18 2010 @@ -0,0 +1,150 @@ +/** + * 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 java.io.IOException; + +import javax.activation.DataHandler; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.eclipse.jetty.servlets.MultiPartFilter; +import org.junit.Test; + +public class MultiPartFormTestWithCustomFilter extends CamelTestSupport { + + private static class MyMultipartFilter extends MultiPartFilter { + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + // set a marker attribute to show that this filter class was used + ((HttpServletResponse)response).addHeader("MyMultipartFilter", "true"); + + super.doFilter(request, response, chain); + } + } + + @Test + public void testSendMultiPartForm() throws Exception { + HttpClient httpclient = new HttpClient(); + File file = new File("src/main/resources/META-INF/NOTICE.txt"); + PostMethod httppost = new PostMethod("http://localhost:9080/test"); + Part[] parts = { + new StringPart("comment", "A binary file of some kind"), + new FilePart(file.getName(), file) + }; + + MultipartRequestEntity reqEntity = new MultipartRequestEntity(parts, httppost.getParams()); + httppost.setRequestEntity(reqEntity); + + int status = httpclient.executeMethod(httppost); + + assertEquals("Get a wrong response status", 200, status); + + String result = httppost.getResponseBodyAsString(); + assertEquals("Get a wrong result", "A binary file of some kind", result); + assertNotNull("Did not use custom multipart filter", httppost.getResponseHeader("MyMultipartFilter")); + } + + @Test + public void testSendMultiPartFormOverrideEnableMultpartFilterFalse() throws Exception { + HttpClient httpclient = new HttpClient(); + + File file = new File("src/main/resources/META-INF/NOTICE.txt"); + + PostMethod httppost = new PostMethod("http://localhost:9080/test2"); + Part[] parts = { + new StringPart("comment", "A binary file of some kind"), + new FilePart(file.getName(), file) + }; + + MultipartRequestEntity reqEntity = new MultipartRequestEntity(parts, httppost.getParams()); + httppost.setRequestEntity(reqEntity); + + int status = httpclient.executeMethod(httppost); + + assertEquals("Get a wrong response status", 200, status); + assertNotNull("Did not use custom multipart filter", httppost.getResponseHeader("MyMultipartFilter")); + } + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("myMultipartFilter", new MyMultipartFilter()); + return jndi; + } + + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + public void configure() throws Exception { + // START SNIPPET: e1 + // Set the jetty temp directory which store the file for multi part form + // camel-jetty will clean up the file after it handled the request. + // The option works rightly from Camel 2.4.0 + getContext().getProperties().put("CamelJettyTempDir", "target"); + + from("jetty://http://localhost:9080/test?multipartFilterRef=myMultipartFilter").process(new Processor() { + public void process(Exchange exchange) throws Exception { + Message in = exchange.getIn(); + assertEquals("Get a wrong attachement size", 1, in.getAttachments().size()); + // The file name is attachment id + DataHandler data = in.getAttachment("NOTICE.txt"); + + assertNotNull("Should get the DataHandle NOTICE.txt", data); + assertEquals("Get a wrong content type", "text/plain", data.getContentType()); + assertEquals("Got the wrong name", "NOTICE.txt", data.getName()); + + assertTrue("We should get the data from the DataHandle", data.getDataSource() + .getInputStream().available() > 0); + + // The other form date can be get from the message header + exchange.getOut().setBody(in.getHeader("comment")); + } + }); + // END SNIPPET: e1 + + // Test to ensure that setting a multipartFilterRef overrides the enableMultipartFilter=false parameter + from("jetty://http://localhost:9080/test2?multipartFilterRef=myMultipartFilter&enableMultipartFilter=false").process(new Processor() { + public void process(Exchange exchange) throws Exception { + Message in = exchange.getIn(); + assertEquals("Get a wrong attachement size", 1, in.getAttachments().size()); + DataHandler data = in.getAttachment("NOTICE.txt"); + + assertNotNull("Should get the DataHandle NOTICE.txt", data); + // The other form date can be get from the message header + exchange.getOut().setBody(in.getHeader("comment")); + } + }); + } + }; + } +} Modified: camel/trunk/components/camel-jetty/src/test/resources/log4j.properties URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/test/resources/log4j.properties?rev=1040823&r1=1040822&r2=1040823&view=diff ============================================================================== --- camel/trunk/components/camel-jetty/src/test/resources/log4j.properties (original) +++ camel/trunk/components/camel-jetty/src/test/resources/log4j.properties Tue Nov 30 23:20:18 2010 @@ -21,7 +21,7 @@ # # The logging properties used for eclipse testing, We want to see debug output on the console. # -log4j.rootLogger=INFO, file +log4j.rootLogger=WARN, file # uncomment the following to enable camel debugging #log4j.logger.org.apache.camel.component.jetty=TRACE