You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2009/02/02 11:34:14 UTC

svn commit: r739958 - in /cxf/branches/2.1.x-fixes: ./ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ rt/fronte...

Author: sergeyb
Date: Mon Feb  2 10:34:13 2009
New Revision: 739958

URL: http://svn.apache.org/viewvc?rev=739958&view=rev
Log:
Merged revisions 739366 via svnmerge from 
https://svn.apache.org/repos/asf/cxf/trunk

........
  r739366 | sergeyb | 2009-01-30 18:23:52 +0000 (Fri, 30 Jan 2009) | 1 line
  
  JAXRS: support for multipart/form-data
........

Added:
    cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm
      - copied unchanged from r739366, cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentForm
Modified:
    cxf/branches/2.1.x-fixes/   (props changed)
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java
    cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
    cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java

Propchange: cxf/branches/2.1.x-fixes/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Feb  2 10:34:13 2009
@@ -1 +1 @@
-/cxf/trunk:686333-686363,686764,686820,687096,687194,687363,687387,687463,687543,687722,687798,687814,687817,687891,687910,687914,688086,688102,688133,688596,688735,688870,689572,689596,689855,689924,690067,690289,691246,691271,691295,691338,691355,691488,691602,691646,691706,691728,692116,692157,692310,692466,692499,693653,693819,694179,694263,694417,694716,694744,694747,694795,694869,694981,694987,694993,695041,695096,695396,695484,695537,695552,695561,695619,695684,695835,695840,695868,695935,695977,696016,696094,696433,696720,697085,697868,698128,699289,700261,700507,700602,700981,701316,701783,701830,701862,702187,702205-702248,702267,702547,702561,702580,702602,702609,702616,702653,702656,702957,703191,703239,703309,703501,703513,703548,704584,704937,704997,705150,705235,705274,705340,705446,705548,705614,705692,705708,706482,706631,706675,706900,706909,707034,707089,707100,707902,708035,708044,708074,708410,708417,708550,708554,709353-709354,709425,710076,710150,71015
 4,711193,711388,711410,711490,711635,711949,711975,712194,712198,712238,712272,712299,712312,712670,712893,713082,713095-713096,713099,713584,713597,713737,713804,713899,714167-714168,714245,714255,717937-717961,718281-718448,718565,718620,718640,718665,718970,719017,719210,719215-719218,719222-719273,719305,719327-719680,720053,720119-720218,720238,720293-720316,720497,721221,721241,721501,722117,722129,722412,722988,723024,723338,723378,723716-723791,724333-724372,724433-724438,724449,724481,724485,724668,724780,724782,724785,724793,724795,724940,725071,725316,725332,725335,725348,725364,725418,725425-725426,725455,725506,725554,725562,725651,725671,725688,725754,725773,725799,725839,726342,726524,726631,726634,726637,726639,726692,726724,726769,726992,727096,727445,727521,727568,727692,727754,727781,727792,728070,728087,728696,728897,729051,729430,729449,729460,729863,730082,730139,730889,730891,731598,731604,731615,731631,731635,732036,732050,732320,732363,732411,732450,
 732710,732773,732827,732829,733512,733582,733901,734367,734462,734666,734762,734772,734812,734836,734965,735113,735252,735722-735723,735729,735734,735751,735782,735787,735987,736332,736343,736352,736358-736362,736408,736423,736448,736491,736621,736726,736736,736738-736739,736766,736825,736852,737032,737046,737061,737069,737124,737237,737246,737299,737356,737494,737498,737761,737817,737849,737855,737994,738166,738178,738201,738210,738242,738244,738265,738516,738583,738863,738937,738983,739367,739451-739452,739799-739800,739867,739876-739877,739922
+/cxf/trunk:686333-686363,686764,686820,687096,687194,687363,687387,687463,687543,687722,687798,687814,687817,687891,687910,687914,688086,688102,688133,688596,688735,688870,689572,689596,689855,689924,690067,690289,691246,691271,691295,691338,691355,691488,691602,691646,691706,691728,692116,692157,692310,692466,692499,693653,693819,694179,694263,694417,694716,694744,694747,694795,694869,694981,694987,694993,695041,695096,695396,695484,695537,695552,695561,695619,695684,695835,695840,695868,695935,695977,696016,696094,696433,696720,697085,697868,698128,699289,700261,700507,700602,700981,701316,701783,701830,701862,702187,702205-702248,702267,702547,702561,702580,702602,702609,702616,702653,702656,702957,703191,703239,703309,703501,703513,703548,704584,704937,704997,705150,705235,705274,705340,705446,705548,705614,705692,705708,706482,706631,706675,706900,706909,707034,707089,707100,707902,708035,708044,708074,708410,708417,708550,708554,709353-709354,709425,710076,710150,71015
 4,711193,711388,711410,711490,711635,711949,711975,712194,712198,712238,712272,712299,712312,712670,712893,713082,713095-713096,713099,713584,713597,713737,713804,713899,714167-714168,714245,714255,717937-717961,718281-718448,718565,718620,718640,718665,718970,719017,719210,719215-719218,719222-719273,719305,719327-719680,720053,720119-720218,720238,720293-720316,720497,721221,721241,721501,722117,722129,722412,722988,723024,723338,723378,723716-723791,724333-724372,724433-724438,724449,724481,724485,724668,724780,724782,724785,724793,724795,724940,725071,725316,725332,725335,725348,725364,725418,725425-725426,725455,725506,725554,725562,725651,725671,725688,725754,725773,725799,725839,726342,726524,726631,726634,726637,726639,726692,726724,726769,726992,727096,727445,727521,727568,727692,727754,727781,727792,728070,728087,728696,728897,729051,729430,729449,729460,729863,730082,730139,730889,730891,731598,731604,731615,731631,731635,732036,732050,732320,732363,732411,732450,
 732710,732773,732827,732829,733512,733582,733901,734367,734462,734666,734762,734772,734812,734836,734965,735113,735252,735722-735723,735729,735734,735751,735782,735787,735987,736332,736343,736352,736358-736362,736408,736423,736448,736491,736621,736726,736736,736738-736739,736766,736825,736852,737032,737046,737061,737069,737124,737237,737246,737299,737356,737494,737498,737761,737817,737849,737855,737994,738166,738178,738201,738210,738242,738244,738265,738516,738583,738863,738937,738983,739366-739367,739451-739452,739799-739800,739867,739876-739877,739922

Propchange: cxf/branches/2.1.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContextImpl.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/tl/ThreadLocalMessageContext.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java Mon Feb  2 10:34:13 2009
@@ -38,31 +38,33 @@
 
 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
-@ConsumeMime({"multipart/related", "multipart/mixed" })
+@ConsumeMime({"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) {
-        
         if (DataHandler.class.isAssignableFrom(type) || DataSource.class.isAssignableFrom(type)
-            || Attachment.class.isAssignableFrom(type)) {
+            || Attachment.class.isAssignableFrom(type) || MultipartBody.class.isAssignableFrom(type)
+            || mediaTypeSupported()) {
             return true;
         }
-        if (mc == null) {
-            return false;
-        }
-        MediaType mt = mc.getHttpHeaders().getMediaType();        
-        if (mt.getType().equals("multipart") 
-            && (mt.getSubtype().equals("related") || mt.getSubtype().equals("mixed"))) {
-            return true;
-        } 
-
         return false;
     }
 
@@ -70,9 +72,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;
             }
@@ -82,8 +86,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);
         }
@@ -109,4 +116,15 @@
         }
         return null;
     }
+    
+    private boolean mediaTypeSupported() {
+
+        if (mc == null) {
+            return false;
+        }
+        MediaType mt = mc.getHttpHeaders().getMediaType();        
+
+        return mt.getType().equals("multipart") && (mt.getSubtype().equals("related") 
+            || mt.getSubtype().equals("mixed") || mt.getSubtype().equals("alternative"));
+    }
 }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProvider.java Mon Feb  2 10:34:13 2009
@@ -27,20 +27,37 @@
 import javax.ws.rs.ConsumeMime;
 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;
 
-@ConsumeMime("application/x-www-form-urlencoded")
+@ConsumeMime({"application/x-www-form-urlencoded", "multipart/form-data" })
 @Provider
 public class FormEncodingReaderProvider implements MessageBodyReader<Object> {
-
+    
+    private static final MediaType MULTIPART_FORM_DATA = MediaType.valueOf("multipart/form-data");
+    
     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 +65,22 @@
     
     public boolean isReadable(Class<?> type, Type genericType, 
                               Annotation[] annotations) {
-        return MultivaluedMap.class.isAssignableFrom(type);
+        return MultivaluedMap.class.isAssignableFrom(type)
+               || mediaTypeSupported() && 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 +106,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(MULTIPART_FORM_DATA)) {
+            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) {
@@ -94,4 +121,14 @@
             validator.validate(params);
         }
     }
+
+    private boolean mediaTypeSupported() {
+
+        if (mc == null) {
+            return false;
+        }
+        MediaType mt = mc.getHttpHeaders().getMediaType();        
+
+        return mt.isCompatible(MULTIPART_FORM_DATA);
+    }
 }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Mon Feb  2 10:34:13 2009
@@ -519,7 +519,6 @@
         return null;
     }
     
-    
     public static MultivaluedMap<String, String> getMatrixParams(String path, boolean decode) {
         int index = path.indexOf(';');
         return index == -1 ? new MetadataMap<String, String>()

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java Mon Feb  2 10:34:13 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 {
@@ -47,6 +51,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));
     }
@@ -63,12 +71,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;    
@@ -87,6 +110,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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java Mon Feb  2 10:34:13 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/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/FormEncodingReaderProviderTest.java Mon Feb  2 10:34:13 2009
@@ -27,10 +27,12 @@
 import javax.ws.rs.ConsumeMime;
 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/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java (original)
+++ cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java Mon Feb  2 10:34:13 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,32 @@
     }
     
     @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 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 testAddBookAsJAXB2() throws Exception {
         String address = "http://localhost:9085/bookstore/books/jaxb2";
         doAddBook(address, "attachmentData", 200);               

Modified: cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java?rev=739958&r1=739957&r2=739958&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java (original)
+++ cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java Mon Feb  2 10:34:13 2009
@@ -33,6 +33,7 @@
 import javax.ws.rs.ProduceMime;
 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 +42,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 +66,38 @@
     }
     
     @POST
+    @Path("/books/form")
+    @ConsumeMime("multipart/form-data")
+    @ProduceMime("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")
+    @ConsumeMime("multipart/form-data")
+    @ProduceMime("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")
+    @ConsumeMime("multipart/form-data")
+    @ProduceMime("text/xml")
+    public Response addBookFromFormBody2() throws Exception {
+        return addBookFromFormBody(AttachmentUtils.getMultipartBody(context));
+    }
+    
+    
+    @POST
     @Path("/books/istream")
     @ProduceMime("text/xml")
     public Response addBookFromInputStream(InputStream is) throws Exception {
@@ -147,6 +181,14 @@
     }
     
     @POST
+    @Path("/books/body")
+    @ProduceMime("text/xml")
+    public Response addBookFromListOfAttachments(MultipartBody body)  
+        throws Exception {
+        return addBookFromListOfAttachments(body.getAllAttachments());
+    }
+    
+    @POST
     @Path("/books/lististreams")
     @ProduceMime("text/xml")
     public Response addBookFromListOfStreams(List<InputStream> atts)