You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2011/10/26 17:41:28 UTC
svn commit: r1189272 - in /cxf/trunk: api/src/main/java/org/apache/cxf/io/
rt/core/src/main/java/org/apache/cxf/attachment/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/fron...
Author: dkulp
Date: Wed Oct 26 15:41:28 2011
New Revision: 1189272
URL: http://svn.apache.org/viewvc?rev=1189272&view=rev
Log:
[CXF-3879] Allow controlling the maximum size of incoming attachments.
Patch from Sam Meder applied.
Modified:
cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java
cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java
Modified: cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java
URL: http://svn.apache.org/viewvc/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java (original)
+++ cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java Wed Oct 26 15:41:28 2011
@@ -43,6 +43,7 @@ import org.apache.cxf.helpers.LoadingByt
public class CachedOutputStream extends OutputStream {
private static final File DEFAULT_TEMP_DIR;
private static final int DEFAULT_THRESHOLD;
+ private static final long DEFAULT_MAX_SIZE;
static {
String s = SystemPropertyAction.getProperty("org.apache.cxf.io.CachedOutputStream.Threshold",
"-1");
@@ -63,12 +64,17 @@ public class CachedOutputStream extends
} else {
DEFAULT_TEMP_DIR = null;
}
+
+ s = System.getProperty("org.apache.cxf.io.CachedOutputStream.MaxSize",
+ "-1");
+ DEFAULT_MAX_SIZE = Long.parseLong(s);
}
protected boolean outputLocked;
protected OutputStream currentStream;
private long threshold = DEFAULT_THRESHOLD;
+ private long maxSize = DEFAULT_MAX_SIZE;
private int totalLength;
@@ -383,13 +389,20 @@ public class CachedOutputStream extends
}
+ private void enforceLimits() throws IOException {
+ if (maxSize > 0 && totalLength > maxSize) {
+ throw new CacheSizeExceededException();
+ }
+ if (inmem && totalLength > threshold && currentStream instanceof ByteArrayOutputStream) {
+ createFileOutputStream();
+ }
+ }
+
public void write(byte[] b, int off, int len) throws IOException {
if (!outputLocked) {
onWrite();
this.totalLength += len;
- if (inmem && totalLength > threshold && currentStream instanceof ByteArrayOutputStream) {
- createFileOutputStream();
- }
+ enforceLimits();
currentStream.write(b, off, len);
}
}
@@ -398,9 +411,7 @@ public class CachedOutputStream extends
if (!outputLocked) {
onWrite();
this.totalLength += b.length;
- if (inmem && totalLength > threshold && currentStream instanceof ByteArrayOutputStream) {
- createFileOutputStream();
- }
+ enforceLimits();
currentStream.write(b);
}
}
@@ -409,9 +420,7 @@ public class CachedOutputStream extends
if (!outputLocked) {
onWrite();
this.totalLength++;
- if (inmem && totalLength > threshold && currentStream instanceof ByteArrayOutputStream) {
- createFileOutputStream();
- }
+ enforceLimits();
currentStream.write(b);
}
}
@@ -498,4 +507,8 @@ public class CachedOutputStream extends
public void setThreshold(long threshold) {
this.threshold = threshold;
}
+
+ public void setMaxSize(long maxSize) {
+ this.maxSize = maxSize;
+ }
}
Modified: cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java (original)
+++ cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java Wed Oct 26 15:41:28 2011
@@ -48,6 +48,8 @@ public class AttachmentDeserializer {
public static final String ATTACHMENT_MEMORY_THRESHOLD = "attachment-memory-threshold";
+ public static final String ATTACHMENT_MAX_SIZE = "attachment-max-size";
+
public static final int THRESHOLD = 1024 * 100; //100K (byte unit)
private static final Pattern CONTENT_TYPE_BOUNDARY_PATTERN = Pattern.compile("boundary=\"?([^\";]*)");
@@ -186,6 +188,15 @@ public class AttachmentDeserializer {
} else {
bos.setThreshold(THRESHOLD);
}
+
+ Object maxSize = message.getContextualProperty(ATTACHMENT_MAX_SIZE);
+ if (maxSize != null) {
+ if (maxSize instanceof Long) {
+ bos.setMaxSize((Long) maxSize);
+ } else {
+ bos.setMaxSize(Long.valueOf((String)maxSize));
+ }
+ }
}
public AttachmentImpl readNext() throws IOException {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java Wed Oct 26 15:41:28 2011
@@ -46,6 +46,7 @@ import org.apache.cxf.attachment.Attachm
import org.apache.cxf.attachment.AttachmentUtil;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.interceptor.AttachmentOutInterceptor;
+import org.apache.cxf.io.CacheSizeExceededException;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.cxf.jaxrs.impl.ProvidersImpl;
@@ -67,7 +68,11 @@ public class MessageContextImpl implemen
String keyValue = key.toString();
if (MultipartBody.INBOUND_MESSAGE_ATTACHMENTS.equals(keyValue)
|| (MultipartBody.INBOUND_MESSAGE_ATTACHMENTS + ".embedded").equals(keyValue)) {
- return createAttachments(key.toString());
+ try {
+ return createAttachments(key.toString());
+ } catch (CacheSizeExceededException e) {
+ throw new WebApplicationException(413);
+ }
}
if (keyValue.equals("WRITE-" + Message.ATTACHMENTS)) {
return m.getExchange().getOutMessage().get(Message.ATTACHMENTS);
@@ -216,6 +221,8 @@ public class MessageContextImpl implemen
m.getExchange().getInMessage().get(AttachmentDeserializer.ATTACHMENT_DIRECTORY));
inMessage.put(AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD,
m.getExchange().getInMessage().get(AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD));
+ inMessage.put(AttachmentDeserializer.ATTACHMENT_MAX_SIZE,
+ m.getExchange().getInMessage().get(AttachmentDeserializer.ATTACHMENT_MAX_SIZE));
inMessage.setContent(InputStream.class,
m.getExchange().getInMessage().get("org.apache.cxf.multipart.embedded.input"));
inMessage.put(Message.CONTENT_TYPE,
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java Wed Oct 26 15:41:28 2011
@@ -61,6 +61,7 @@ public class FormEncodingProvider implem
@Context private MessageContext mc;
private String attachmentDir;
private String attachmentThreshold;
+ private String attachmentMaxSize;
private boolean expectEncoded;
@@ -76,6 +77,10 @@ public class FormEncodingProvider implem
attachmentThreshold = threshold;
}
+ public void setAttachmentMaxSize(String maxSize) {
+ attachmentMaxSize = maxSize;
+ }
+
public void setValidator(FormValidator formValidator) {
validator = formValidator;
}
@@ -151,7 +156,7 @@ public class FormEncodingProvider implem
InputStream is, MediaType mt, boolean decode) {
if (mt.isCompatible(MediaType.MULTIPART_FORM_DATA_TYPE)) {
MultipartBody body =
- AttachmentUtils.getMultipartBody(mc, attachmentDir, attachmentThreshold);
+ AttachmentUtils.getMultipartBody(mc, attachmentDir, attachmentThreshold, attachmentMaxSize);
FormUtils.populateMapFromMultipart(params, body, decode);
} else {
String enc = HttpUtils.getEncoding(mt, "UTF-8");
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java Wed Oct 26 15:41:28 2011
@@ -82,6 +82,7 @@ public class MultipartProvider extends A
private MessageContext mc;
private String attachmentDir;
private String attachmentThreshold;
+ private String attachmentMaxSize;
public void setMessageContext(MessageContext context) {
this.mc = context;
@@ -95,6 +96,10 @@ public class MultipartProvider extends A
attachmentThreshold = threshold;
}
+ public void setAttachmentMaxSize(String maxSize) {
+ attachmentMaxSize = maxSize;
+ }
+
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mt) {
return isSupported(type, genericType, annotations, mt);
@@ -131,8 +136,8 @@ public class MultipartProvider extends A
MultivaluedMap<String, String> headers, InputStream is)
throws IOException, WebApplicationException {
checkContentLength();
- List<Attachment> infos =
- AttachmentUtils.getAttachments(mc, attachmentDir, attachmentThreshold);
+ List<Attachment> infos = AttachmentUtils.getAttachments(
+ mc, attachmentDir, attachmentThreshold, attachmentMaxSize);
if (Collection.class.isAssignableFrom(c)
&& AnnotationUtils.getAnnotation(anns, Multipart.class) == null) {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java Wed Oct 26 15:41:28 2011
@@ -72,13 +72,16 @@ public final class AttachmentUtils {
}
public static MultipartBody getMultipartBody(MessageContext mc,
- String attachmentDir, String attachmentThreshold) {
+ String attachmentDir, String attachmentThreshold, String attachmentMaxSize) {
if (attachmentDir != null) {
mc.put(AttachmentDeserializer.ATTACHMENT_DIRECTORY, attachmentDir);
}
if (attachmentThreshold != null) {
mc.put(AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD, attachmentThreshold);
}
+ if (attachmentMaxSize != null) {
+ mc.put(AttachmentDeserializer.ATTACHMENT_MAX_SIZE, attachmentMaxSize);
+ }
boolean embeddedAttachment = mc.get("org.apache.cxf.multipart.embedded") != null;
String propertyName = embeddedAttachment ? MultipartBody.INBOUND_MESSAGE_ATTACHMENTS + ".embedded"
@@ -88,8 +91,11 @@ public final class AttachmentUtils {
}
public static List<Attachment> getAttachments(MessageContext mc,
- String attachmentDir, String attachmentThreshold) {
- return getMultipartBody(mc, attachmentDir, attachmentThreshold).getAllAttachments();
+ String attachmentDir, String attachmentThreshold, String attachmentMaxSize) {
+ return getMultipartBody(mc,
+ attachmentDir,
+ attachmentThreshold,
+ attachmentMaxSize).getAllAttachments();
}
public static Attachment getMultipart(Class<Object> c, Annotation[] anns,
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java Wed Oct 26 15:41:28 2011
@@ -43,6 +43,10 @@ import org.apache.commons.httpclient.Htt
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
+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.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
@@ -526,6 +530,28 @@ public class JAXRSMultipartTest extends
}
}
+ @Test
+ public void testMultipartRequestTooLarge() throws Exception {
+ PostMethod post = new PostMethod("http://localhost:" + PORT + "/bookstore/books/image");
+ String ct = "multipart/mixed";
+ post.setRequestHeader("Content-Type", ct);
+ Part[] parts = new Part[1];
+ parts[0] = new FilePart("image",
+ new ByteArrayPartSource("testfile.png", new byte[1024 * 1024 * 15]),
+ "image/png", null);
+ post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
+
+ HttpClient httpclient = new HttpClient();
+
+ try {
+ int result = httpclient.executeMethod(post);
+ assertEquals(413, result);
+ } finally {
+ // Release current connection to the connection pool once you are done
+ post.releaseConnection();
+ }
+ }
+
private void doAddBook(String address, String resourceName, int status) throws Exception {
doAddBook("multipart/related", address, resourceName, status);
}
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java?rev=1189272&r1=1189271&r2=1189272&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java Wed Oct 26 15:41:28 2011
@@ -19,15 +19,22 @@
package org.apache.cxf.systest.jaxrs;
+import java.util.Collections;
+
+import org.apache.cxf.attachment.AttachmentDeserializer;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
public class MultipartServer extends AbstractBusTestServerBase {
public static final String PORT = allocatePort(MultipartServer.class);
protected void run() {
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(MultipartStore.class);
+ sf.setProperties(Collections.<String, Object>singletonMap(
+ AttachmentDeserializer.ATTACHMENT_MAX_SIZE,
+ String.valueOf(1024 * 1024 * 10)));
//default lifecycle is per-request, change it to singleton
sf.setResourceProvider(MultipartStore.class,
new SingletonResourceProvider(new MultipartStore()));