Author: sergeyb
Date: Fri Jan 30 18:23:52 2009
New Revision: 739366
URL: http://svn.apache.org/viewvc?rev=739366&view=rev
Log:
JAXRS: support for multipart/form-data
Added:
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.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/ext/multipart/Attachment.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java
Fri Jan 30 18:23:52 2009
@@ -36,7 +36,7 @@
public interface MessageContext {
Object get(Object key);
- void put(Object key, Object value);
+ void put(Object key, Object value, boolean outbound);
UriInfo getUriInfo();
Request getRequest();
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=739366&r1=739365&r2=739366&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
Fri Jan 30 18:23:52 2009
@@ -112,8 +112,12 @@
return JAXRSUtils.createServletResourceValue(m, ServletContext.class);
}
- public void put(Object key, Object value) {
- throw new UnsupportedOperationException("MessageContext.put() is not
supported yet");
+ public void put(Object key, Object value, boolean outbound) {
+ if (outbound) {
+ throw new UnsupportedOperationException(
+ "MessageContext.put() is not supported for outbound
properties");
+ }
+ m.put(key.toString(), value);
}
private MultipartBody createAttachments(String propertyName) {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
Fri Jan 30 18:23:52 2009
@@ -61,7 +61,8 @@
}
public ContentDisposition getContentDisposition() {
- String header = headers.getFirst("Content-Disposition");
+ String header = getHeader("Content-Disposition");
+
return header == null ? null : new ContentDisposition(header);
}
@@ -79,11 +80,13 @@
}
public String getHeader(String name) {
- return headers.getFirst(name);
+ String header = headers.getFirst(name);
+ return header == null ? headers.getFirst(name.toLowerCase()) : header;
}
public List<String> getHeaderAsList(String name) {
- return headers.get(name);
+ List<String> header = headers.get(name);
+ return header == null ? headers.get(name.toLowerCase()) : header;
}
public MultivaluedMap<String, String> getHeaders() {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
Fri Jan 30 18:23:52 2009
@@ -73,5 +73,12 @@
return atts.size() > 0 ? atts.get(0) : null;
}
-
+ public Attachment getAttachment(String contentId) {
+ for (Attachment a : atts) {
+ if (contentId.equalsIgnoreCase(a.getContentId())) {
+ return a;
+ }
+ }
+ return null;
+ }
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
Fri Jan 30 18:23:52 2009
@@ -78,9 +78,9 @@
return get() != null ? get().getRequest() : null;
}
- public void put(Object key, Object value) {
+ public void put(Object key, Object value, boolean outbound) {
if (get() != null) {
- get().put(key, value);
+ get().put(key, value, outbound);
}
throw new IllegalStateException("MessageContext is not set");
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
Fri Jan 30 18:23:52 2009
@@ -29,7 +29,10 @@
public class AttachmentInputInterceptor extends AttachmentInInterceptor {
private static final List<String> DEFAULT_TYPES =
- Arrays.asList(new String[]{"multipart/related", "multipart/mixed"});
+ Arrays.asList(new String[]{"multipart/related",
+ "multipart/mixed",
+ "multipart/alternative",
+ "multipart/form-data"});
private List<String> types = DEFAULT_TYPES;
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
Fri Jan 30 18:23:52 2009
@@ -38,23 +38,32 @@
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
@Provider
-...@consumes({"multipart/related", "multipart/mixed" })
+...@consumes({"multipart/related", "multipart/mixed", "multipart/alternative"
})
public class ActivationProvider implements MessageBodyReader<Object> {
@Context
private MessageContext mc;
+ private String attachmentDir;
+ private String attachmentThreshold;
+
+ public void setAttachmentDirectory(String dir) {
+ attachmentDir = dir;
+ }
+
+ public void setAttachmentThreshold(String threshold) {
+ attachmentThreshold = threshold;
+ }
public boolean isReadable(Class<?> type, Type genericType, Annotation[]
annotations,
MediaType mt) {
- if (DataHandler.class.isAssignableFrom(type)
- || DataSource.class.isAssignableFrom(type)
- || Attachment.class.isAssignableFrom(type)
- || (mt.getType().equals("multipart")
- && (mt.getSubtype().equals("related") ||
mt.getSubtype().equals("mixed")))) {
+ if (DataHandler.class.isAssignableFrom(type) ||
DataSource.class.isAssignableFrom(type)
+ || Attachment.class.isAssignableFrom(type) ||
MultipartBody.class.isAssignableFrom(type)
+ || mediaTypeSupported(mt)) {
return true;
}
return false;
@@ -64,9 +73,11 @@
MultivaluedMap<String, String> headers, InputStream
is)
throws IOException, WebApplicationException {
+ List<Attachment> infos =
+ AttachmentUtils.getAttachments(mc, attachmentDir,
attachmentThreshold);
+
if (List.class.isAssignableFrom(c)) {
Class<?> actual = InjectionUtils.getActualType(t);
- List<Attachment> infos = AttachmentUtils.getAttachments(mc);
if (actual.isAssignableFrom(Attachment.class)) {
return infos;
}
@@ -76,8 +87,11 @@
}
return objects;
}
+ if (MultipartBody.class.isAssignableFrom(c)) {
+ return new MultipartBody(infos);
+ }
- Attachment multipart = AttachmentUtils.getMultipart(c, anns, mt, mc);
+ Attachment multipart = AttachmentUtils.getMultipart(c, anns, mt,
infos);
if (multipart != null) {
return fromAttachment(multipart, c, t, anns);
}
@@ -103,4 +117,9 @@
}
return null;
}
+
+ private boolean mediaTypeSupported(MediaType mt) {
+ return mt.getType().equals("multipart") &&
(mt.getSubtype().equals("related")
+ || mt.getSubtype().equals("mixed") ||
mt.getSubtype().equals("alternative"));
+ }
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java
Fri Jan 30 18:23:52 2009
@@ -27,20 +27,35 @@
import javax.ws.rs.Consumes;
import javax.ws.rs.Encoded;
import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.utils.AnnotationUtils;
import org.apache.cxf.jaxrs.utils.FormUtils;
+import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
-...@consumes("application/x-www-form-urlencoded")
+...@consumes({"application/x-www-form-urlencoded", "multipart/form-data" })
@Provider
public class FormEncodingReaderProvider implements MessageBodyReader<Object> {
-
+
private FormValidator validator;
+ @Context private MessageContext mc;
+ private String attachmentDir;
+ private String attachmentThreshold;
+
+ public void setAttachmentDirectory(String dir) {
+ attachmentDir = dir;
+ }
+
+ public void setAttachmentThreshold(String threshold) {
+ attachmentThreshold = threshold;
+ }
public void setValidator(FormValidator formValidator) {
validator = formValidator;
@@ -48,17 +63,23 @@
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mt) {
- return MultivaluedMap.class.isAssignableFrom(type);
+ return MultivaluedMap.class.isAssignableFrom(type)
+ || mt.isCompatible(MediaType.MULTIPART_FORM_DATA_TYPE)
+ && MultipartBody.class.isAssignableFrom(type);
}
- public MultivaluedMap<String, String> readFrom(
+ public Object readFrom(
Class<Object> clazz, Type genericType, Annotation[] annotations,
MediaType type,
MultivaluedMap<String, String> headers, InputStream is)
throws IOException {
try {
-
+
+ if (MultipartBody.class.isAssignableFrom(clazz)) {
+ return AttachmentUtils.getMultipartBody(mc);
+ }
+
MultivaluedMap<String, String> params = createMap(clazz);
- populateMap(params, is,
+ populateMap(params, is, type,
AnnotationUtils.getAnnotation(annotations,
Encoded.class) == null);
validateMap(params);
return params;
@@ -84,9 +105,14 @@
* @return a Map of parameters.
*/
protected void populateMap(MultivaluedMap<String, String> params,
- InputStream is,
- boolean decode) {
- FormUtils.populateMap(params, FormUtils.readBody(is), decode);
+ InputStream is, MediaType mt, boolean decode) {
+ if (mt.isCompatible(MediaType.MULTIPART_FORM_DATA_TYPE)) {
+ MultipartBody body =
+ AttachmentUtils.getMultipartBody(mc, attachmentDir,
attachmentThreshold);
+ FormUtils.populateMapFromMultipart(params, body, decode);
+ } else {
+ FormUtils.populateMapFromString(params, FormUtils.readBody(is),
decode);
+ }
}
protected void validateMap(MultivaluedMap<String, String> params) {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
Fri Jan 30 18:23:52 2009
@@ -20,6 +20,7 @@
package org.apache.cxf.jaxrs.utils;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
@@ -29,9 +30,14 @@
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
public final class FormUtils {
+ private static final String FORM_DATA_TYPE = "form-data";
+
private FormUtils() {
}
@@ -46,8 +52,8 @@
}
}
- public static void populateMap(MultivaluedMap<String, String> params,
- String postBody, boolean decode) {
+ public static void populateMapFromString(MultivaluedMap<String, String>
params,
+ String postBody, boolean decode) {
if (!StringUtils.isEmpty(postBody)) {
List<String> parts = Arrays.asList(postBody.split("&"));
for (String part : parts) {
@@ -66,4 +72,24 @@
}
}
}
+
+ public static void populateMapFromMultipart(MultivaluedMap<String, String>
params,
+ MultipartBody body,
+ boolean decode) {
+ List<Attachment> atts = body.getAllAttachments();
+ for (Attachment a : atts) {
+ ContentDisposition cd = a.getContentDisposition();
+ if (cd == null || !FORM_DATA_TYPE.equalsIgnoreCase(cd.getType())
+ || cd.getParameter("name") == null) {
+ throw new WebApplicationException(415);
+ }
+ String name = cd.getParameter("name").replace("\"",
"").replace("'", "");
+ try {
+ String value =
IOUtils.toString(a.getDataHandler().getInputStream());
+ params.add(name, decode ? JAXRSUtils.uriDecode(value) : value);
+ } catch (IOException ex) {
+ throw new WebApplicationException(415);
+ }
+ }
+ }
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
Fri Jan 30 18:23:52 2009
@@ -132,6 +132,18 @@
return (Class<?>)paramType.getActualTypeArguments()[0];
}
+ public static Class<?> getActualType(Type genericType, int i) {
+ if (genericType == null
+ ||
!ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
+ return null;
+ }
+ ParameterizedType paramType = (ParameterizedType)genericType;
+ if (i < paramType.getActualTypeArguments().length) {
+ return (Class<?>)paramType.getActualTypeArguments()[i];
+ }
+ return null;
+ }
+
public static void injectThroughMethod(Object requestObject,
Method method,
Object parameterValue) {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
Fri Jan 30 18:23:52 2009
@@ -76,6 +76,7 @@
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.MessageContextImpl;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
@@ -90,6 +91,7 @@
import org.apache.cxf.jaxrs.model.URITemplate;
import org.apache.cxf.jaxrs.provider.AbstractConfigurableProvider;
import org.apache.cxf.jaxrs.provider.ProviderFactory;
+import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
@@ -531,14 +533,23 @@
Class<?> pClass, Type genericType,
String defaultValue,
boolean decode) {
+
+ MessageContext mc = new MessageContextImpl(m);
+ MediaType mt = mc.getHttpHeaders().getMediaType();
+
MultivaluedMap<String, String> params = new MetadataMap<String,
String>();
- String body = (String)m.get("org.apache.cxf.jaxrs.provider.form.body");
- if (body == null) {
- body = FormUtils.readBody(m.getContent(InputStream.class));
- m.put("org.apache.cxf.jaxrs.provider.form.body", body);
+
+ if (mt == null ||
mt.isCompatible(MediaType.APPLICATION_FORM_URLENCODED_TYPE)) {
+ String body =
(String)m.get("org.apache.cxf.jaxrs.provider.form.body");
+ if (body == null) {
+ body = FormUtils.readBody(m.getContent(InputStream.class));
+ m.put("org.apache.cxf.jaxrs.provider.form.body", body);
+ }
+ FormUtils.populateMapFromString(params, (String)body, decode);
+ } else {
+ MultipartBody body = AttachmentUtils.getMultipartBody(mc);
+ FormUtils.populateMapFromMultipart(params, body, decode);
}
- // TODO : this is done per every form parameter hence it needs to be
refactored
- FormUtils.populateMap(params, body, decode);
String basePath = HttpUtils.getOriginalAddress(m);
if ("".equals(key)) {
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=739366&r1=739365&r2=739366&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
Fri Jan 30 18:23:52 2009
@@ -29,14 +29,18 @@
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import org.apache.cxf.attachment.AttachmentDeserializer;
import org.apache.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.utils.AnnotationUtils;
+import org.apache.cxf.jaxrs.utils.FormUtils;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
public final class AttachmentUtils {
@@ -46,6 +50,10 @@
private AttachmentUtils() {
}
+ public static MultipartBody getMultipartBody(MessageContext mc) {
+ return
(MultipartBody)mc.get(MultipartBody.INBOUND_MESSAGE_ATTACHMENTS);
+ }
+
public static Map<String, Attachment>
getChildAttachmentsMap(MessageContext mc) {
return fromListToMap(getChildAttachments(mc));
}
@@ -62,12 +70,27 @@
return
((MultipartBody)mc.get(MultipartBody.INBOUND_MESSAGE_ATTACHMENTS)).getAllAttachments();
}
+ public static MultipartBody getMultipartBody(MessageContext mc,
+ String attachmentDir, String attachmentThreshold) {
+ if (attachmentDir != null) {
+ mc.put(AttachmentDeserializer.ATTACHMENT_DIRECTORY, attachmentDir,
false);
+ }
+ if (attachmentThreshold != null) {
+ mc.put(AttachmentDeserializer.ATTACHMENT_MEMORY_THRESHOLD,
attachmentThreshold, false);
+ }
+ return
(MultipartBody)mc.get(MultipartBody.INBOUND_MESSAGE_ATTACHMENTS);
+ }
+
+ public static List<Attachment> getAttachments(MessageContext mc,
+ String attachmentDir, String attachmentThreshold) {
+ return getMultipartBody(mc, attachmentDir,
attachmentThreshold).getAllAttachments();
+ }
+
public static Attachment getMultipart(Class<Object> c, Annotation[] anns,
- MediaType mt, MessageContext mc) throws IOException {
- List<Attachment> infos = AttachmentUtils.getAttachments(mc);
+ MediaType mt, List<Attachment> infos) throws IOException {
Multipart id = AnnotationUtils.getAnnotation(anns, Multipart.class);
if (id != null) {
- for (Attachment a : getAttachments(mc)) {
+ for (Attachment a : infos) {
if (a.getContentId().equals(id.value())) {
checkMediaTypes(a.getContentType(), id.type());
return a;
@@ -86,6 +109,19 @@
return infos.size() > 0 ? infos.get(0) : null;
}
+ @SuppressWarnings("unchecked")
+ public static <T> MultivaluedMap<String, T> populateFormMap(MessageContext
mc, Class<T> cls) {
+ MultivaluedMap<String, T> data = new MetadataMap<String, T>();
+ FormUtils.populateMapFromMultipart((MultivaluedMap)data,
+
AttachmentUtils.getMultipartBody(mc), true);
+ return data;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static MultivaluedMap<String, String>
populateFormMap(MessageContext mc) {
+ return populateFormMap(mc, String.class);
+ }
+
private static Map<String, Attachment> fromListToMap(List<Attachment>
atts) {
Map<String, Attachment> map = new LinkedHashMap<String, Attachment>();
for (Attachment a : atts) {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
Fri Jan 30 18:23:52 2009
@@ -43,6 +43,17 @@
assertEquals(atts.get(1), b.getChildAttachments().get(0));
}
+ @Test
+ public void testGetAttachmentsById() {
+ List<Attachment> atts = new ArrayList<Attachment>();
+ atts.add(createAttachment("p1"));
+ atts.add(createAttachment("p2"));
+ MultipartBody b = new MultipartBody(atts);
+ assertEquals(atts.get(0), b.getAttachment("p1"));
+ assertEquals(atts.get(1), b.getAttachment("p2"));
+ assertNull(b.getAttachment("p3"));
+ }
+
private Attachment createAttachment(String id) {
return new Attachment(id,
new DataHandler(new ByteArrayDataSource(new byte[]{1},
"application/octet-stream")),
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java
Fri Jan 30 18:23:52 2009
@@ -27,10 +27,12 @@
import javax.ws.rs.Consumes;
import javax.ws.rs.Encoded;
import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -49,7 +51,8 @@
public void testReadFrom() throws Exception {
InputStream is =
getClass().getResourceAsStream("singleValPostBody.txt");
MultivaluedMap<String, String> mvMap =
- ferp.readFrom((Class)MultivaluedMap.class, null, new
Annotation[]{}, null, null, is);
+ (MultivaluedMap<String,
String>)ferp.readFrom((Class)MultivaluedMap.class, null,
+ new Annotation[]{},
MediaType.APPLICATION_FORM_URLENCODED_TYPE, null, is);
assertEquals("Wrong entry for foo", "bar", mvMap.getFirst("foo"));
assertEquals("Wrong entry for boo", "far", mvMap.getFirst("boo"));
@@ -61,9 +64,9 @@
String values = "foo=1+2&bar=1+3";
MultivaluedMap<String, String> mvMap =
- ferp.readFrom((Class)MultivaluedMap.class, null,
- new Annotation[]{}, null, null,
- new ByteArrayInputStream(values.getBytes()));
+ (MultivaluedMap<String,
String>)ferp.readFrom((Class)MultivaluedMap.class, null,
+ new Annotation[]{},
MediaType.APPLICATION_FORM_URLENCODED_TYPE, null,
+ new ByteArrayInputStream(values.getBytes()));
assertEquals("Wrong entry for foo", "1 2", mvMap.getFirst("foo"));
assertEquals("Wrong entry for boo", "1 3", mvMap.getFirst("bar"));
@@ -75,9 +78,10 @@
String values = "foo=1+2&bar=1+3";
MultivaluedMap<String, String> mvMap =
- ferp.readFrom((Class)MultivaluedMap.class, null,
- new
Annotation[]{CustomMap.class.getAnnotations()[0]}, null, null,
- new ByteArrayInputStream(values.getBytes()));
+ (MultivaluedMap<String,
String>)ferp.readFrom((Class)MultivaluedMap.class, null,
+ new Annotation[]{CustomMap.class.getAnnotations()[0]},
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE, null,
+ new ByteArrayInputStream(values.getBytes()));
assertEquals("Wrong entry for foo", "1+2", mvMap.getFirst("foo"));
assertEquals("Wrong entry for boo", "1+3", mvMap.getFirst("bar"));
@@ -89,7 +93,8 @@
String values = "foo=1+2&bar=1+3&baz=4";
MultivaluedMap<String, String> mvMap =
- ferp.readFrom((Class)CustomMap.class, null, new Annotation[]{},
null, null,
+ (MultivaluedMap<String,
String>)ferp.readFrom((Class)CustomMap.class, null,
+ new Annotation[]{},
MediaType.APPLICATION_FORM_URLENCODED_TYPE, null,
new ByteArrayInputStream(values.getBytes()));
assertEquals(3, mvMap.size());
assertEquals(1, mvMap.get("foo").size());
@@ -107,8 +112,8 @@
String values = "foo=1+2&bar=line1%0D%0Aline+2&baz=4";
MultivaluedMap<String, String> mvMap =
- ferp.readFrom((Class)CustomMap.class, null,
- new Annotation[]{}, null, null,
+ (MultivaluedMap<String,
String>)ferp.readFrom((Class)CustomMap.class, null,
+ new Annotation[]{},
MediaType.APPLICATION_FORM_URLENCODED_TYPE, null,
new ByteArrayInputStream(values.getBytes()));
assertEquals(3, mvMap.size());
assertEquals(1, mvMap.get("foo").size());
@@ -123,12 +128,13 @@
@SuppressWarnings("unchecked")
@Test
- public void testvalidation() throws Exception {
+ public void testValidation() throws Exception {
ferp.setValidator(new CustomFormValidator());
String values = "foo=1+2&bar=1+3";
try {
- ferp.readFrom((Class)CustomMap.class, null, new Annotation[]{},
null, null,
+ ferp.readFrom((Class)CustomMap.class, null, new Annotation[]{},
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE, null,
new ByteArrayInputStream(values.getBytes()));
fail();
} catch (WebApplicationException ex) {
@@ -144,7 +150,8 @@
InputStream is =
getClass().getResourceAsStream("multiValPostBody.txt");
MultivaluedMap<String, String> mvMap =
- ferp.readFrom((Class)MultivaluedMap.class, null, new
Annotation[]{}, null, null, is);
+ (MultivaluedMap<String,
String>)ferp.readFrom((Class)MultivaluedMap.class, null,
+ new Annotation[]{},
MediaType.APPLICATION_FORM_URLENCODED_TYPE, null, is);
List<String> vals = mvMap.get("foo");
assertEquals("Wrong size for foo params", 2, vals.size());
Modified:
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
(original)
+++
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
Fri Jan 30 18:23:52 2009
@@ -37,7 +37,7 @@
@BeforeClass
public static void startServers() throws Exception {
assertTrue("server did not launch correctly",
- launchServer(MultipartServer.class, true));
+ launchServer(MultipartServer.class));
}
@Test
@@ -95,6 +95,42 @@
}
@Test
+ public void testAddBookAsBody() throws Exception {
+ String address = "http://localhost:9085/bookstore/books/body";
+ doAddBook(address, "attachmentData", 200);
+ }
+
+ @Test
+ public void testAddBookFormData() throws Exception {
+ String address = "http://localhost:9085/bookstore/books/form";
+ doAddBook("multipart/form-data", address, "attachmentForm", 200);
+ }
+
+ @Test
+ public void testAddBookFormParam() throws Exception {
+ String address = "http://localhost:9085/bookstore/books/formparam";
+ doAddBook("multipart/form-data", address, "attachmentForm", 200);
+ }
+
+ @Test
+ public void testAddBookFormBody() throws Exception {
+ String address = "http://localhost:9085/bookstore/books/formbody";
+ doAddBook("multipart/form-data", address, "attachmentForm", 200);
+ }
+
+ @Test
+ public void testAddBookFormBody2() throws Exception {
+ String address = "http://localhost:9085/bookstore/books/formbody2";
+ doAddBook("multipart/form-data", address, "attachmentForm", 200);
+ }
+
+ @Test
+ public void testAddBookFormParamBean() throws Exception {
+ String address = "http://localhost:9085/bookstore/books/formparambean";
+ doAddBook("multipart/form-data", address, "attachmentForm", 200);
+ }
+
+ @Test
public void testAddBookAsJAXB2() throws Exception {
String address = "http://localhost:9085/bookstore/books/jaxb2";
doAddBook(address, "attachmentData", 200);
Modified:
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java?rev=739366&r1=739365&r2=739366&view=diff
==============================================================================
---
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java
(original)
+++
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java
Fri Jan 30 18:23:52 2009
@@ -28,11 +28,13 @@
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
@@ -41,6 +43,7 @@
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
@Path("/bookstore")
@@ -64,6 +67,57 @@
}
@POST
+ @Path("/books/form")
+ @Consumes("multipart/form-data")
+ @Produces("text/xml")
+ public Response addBookFromForm(MultivaluedMap<String, String> data)
throws Exception {
+ Book b = new Book();
+ b.setId(Long.valueOf(data.getFirst("id")));
+ b.setName(data.getFirst("name"));
+ return Response.ok(b).build();
+ }
+
+ @POST
+ @Path("/books/formbody")
+ @Consumes("multipart/form-data")
+ @Produces("text/xml")
+ public Response addBookFromFormBody(MultipartBody body) throws Exception {
+ MultivaluedMap<String, String> data =
AttachmentUtils.populateFormMap(context);
+ Book b = new Book();
+ b.setId(Long.valueOf(data.getFirst("id")));
+ b.setName(data.getFirst("name"));
+ return Response.ok(b).build();
+ }
+
+ @POST
+ @Path("/books/formbody2")
+ @Consumes("multipart/form-data")
+ @Produces("text/xml")
+ public Response addBookFromFormBody2() throws Exception {
+ return addBookFromFormBody(AttachmentUtils.getMultipartBody(context));
+ }
+
+
+ @POST
+ @Path("/books/formparam")
+ @Produces("text/xml")
+ public Response addBookFromFormParam(@FormParam("name") String title,
+ @FormParam("id") Long id) throws
Exception {
+ Book b = new Book();
+ b.setId(id);
+ b.setName(title);
+ return Response.ok(b).build();
+ }
+
+ @POST
+ @Path("/books/formparambean")
+ @Produces("text/xml")
+ public Response addBookFromFormParam(@FormParam("") Book b) throws
Exception {
+ return Response.ok(b).build();
+ }
+
+
+ @POST
@Path("/books/istream")
@Produces("text/xml")
public Response addBookFromInputStream(InputStream is) throws Exception {
@@ -147,6 +201,14 @@
}
@POST
+ @Path("/books/body")
+ @Produces("text/xml")
+ public Response addBookFromListOfAttachments(MultipartBody body)
+ throws Exception {
+ return addBookFromListOfAttachments(body.getAllAttachments());
+ }
+
+ @POST
@Path("/books/lististreams")
@Produces("text/xml")
public Response addBookFromListOfStreams(List<InputStream> atts)
Added:
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm?rev=739366&view=auto
==============================================================================
---
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm
(added)
+++
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm
Fri Jan 30 18:23:52 2009
@@ -0,0 +1,10 @@
+
+------=_Part_4_701508.1145579811786
+Content-Disposition: form-data; name="name"
+
+CXF+in+Action+-+2
+------=_Part_4_701508.1145579811786
+Content-Disposition: form-data ; name = "id"
+
+124
+------=_Part_4_701508.1145579811786--
\ No newline at end of file