cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r738583 - in /cxf/trunk: rt/core/src/main/java/org/apache/cxf/attachment/ rt/core/src/main/java/org/apache/cxf/interceptor/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/ rt/f...
Date Wed, 28 Jan 2009 18:54:22 GMT
Author: sergeyb
Date: Wed Jan 28 18:54:21 2009
New Revision: 738583

URL: http://svn.apache.org/viewvc?rev=738583&view=rev
Log:
JAXRS : improving the support for multiparts 

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java   (with props)
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentData3
Removed:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MultipartID.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/MultipartInfo.java
Modified:
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
    cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentInInterceptor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java
    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/impl/HttpHeadersImpl.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/utils/multipart/AttachmentUtils.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/MultipartServer.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java

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=738583&r1=738582&r2=738583&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 Jan 28 18:54:21 2009
@@ -23,16 +23,14 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PushbackInputStream;
-import java.net.URLDecoder;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.activation.DataHandler;
 import javax.activation.DataSource;
-import javax.mail.Header;
 import javax.mail.MessagingException;
 import javax.mail.internet.InternetHeaders;
 
@@ -72,11 +70,17 @@
     private InputStream body;
     
     private Set<DelegatingInputStream> loaded = new HashSet<DelegatingInputStream>();
+    private List<String> supportedTypes;
 
     public AttachmentDeserializer(Message message) {
-        this.message = message;
+        this(message, Collections.singletonList("multipart/related"));
     }
 
+    public AttachmentDeserializer(Message message, List<String> supportedTypes) {
+        this.message = message;
+        this.supportedTypes = supportedTypes;
+    }
+    
     public void initializeAttachments() throws IOException {
         initializeRootMessage();
 
@@ -95,7 +99,7 @@
             throw new IllegalStateException("An InputStream must be provided!");
         }
 
-        if (contentType.toLowerCase().indexOf("multipart/related") != -1) {
+        if (AttachmentUtil.isTypeSupported(contentType.toLowerCase(), supportedTypes)) {
             String boundaryString = findBoundaryFromContentType(contentType);
             if (null == boundaryString) {                
                 boundaryString = findBoundaryFromInputStream();
@@ -113,8 +117,7 @@
             }
 
             try {
-                // TODO: Do we need to copy these headers somewhere?
-                new InternetHeaders(stream);
+                message.put(InternetHeaders.class.getName(), new InternetHeaders(stream));
             } catch (MessagingException e) {
                 throw new RuntimeException(e);
             }
@@ -188,19 +191,7 @@
             throw new RuntimeException(e);
         }
 
-        String id = headers.getHeader("Content-ID", null);
-        if (id != null && id.startsWith("<")) {
-            id = id.substring(1, id.length() - 1);
-        } else {
-            //no Content-ID, set cxf default ID
-            id = "Content-ID: <root.message@cxf.apache.org";
-        }
-
-        id = URLDecoder.decode(id.startsWith("cid:") ? id.substring(4) : id, "UTF-8");
-
-        AttachmentImpl att = new AttachmentImpl(id);
-        setupAttachment(att, headers);
-        return att;
+        return (AttachmentImpl)createAttachment(headers);
     }
 
     private void cacheStreamedAttachments() throws IOException {
@@ -286,33 +277,10 @@
      * @return
      * @throws IOException
      */
-    private void setupAttachment(AttachmentImpl att, InternetHeaders headers) throws IOException {
-        MimeBodyPartInputStream partStream = new MimeBodyPartInputStream(stream, boundary, pbAmount);
-
-        final String ct = headers.getHeader("Content-Type", null);
-        
-        boolean quotedPrintable = false;
-        
-        for (Enumeration<?> e = headers.getAllHeaders(); e.hasMoreElements();) {
-            Header header = (Header) e.nextElement();
-            if (header.getName().equalsIgnoreCase("Content-Transfer-Encoding")) {
-                if (header.getValue().equalsIgnoreCase("binary")) {
-                    att.setXOP(true);
-                } else if (header.getValue().equalsIgnoreCase("quoted-printable")) {
-                    quotedPrintable = true;
-                }
-            }
-            att.setHeader(header.getName(), header.getValue());
-        }
-        
-        DelegatingInputStream is = new DelegatingInputStream(partStream);
-        if (quotedPrintable) {
-            DataSource source = new AttachmentDataSource(ct, new QuotedPrintableDecoderStream(is));
-            att.setDataHandler(new DataHandler(source));
-        } else {
-            DataSource source = new AttachmentDataSource(ct, is);
-            att.setDataHandler(new DataHandler(source));
-        }
+    private Attachment createAttachment(InternetHeaders headers) throws IOException {
+        InputStream partStream = 
+            new DelegatingInputStream(new MimeBodyPartInputStream(stream, boundary, pbAmount));
+        return AttachmentUtil.createAttachment(partStream, headers);
     }
 
     public boolean isLazyLoading() {

Modified: cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java?rev=738583&r1=738582&r2=738583&view=diff
==============================================================================
--- cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java (original)
+++ cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java Wed Jan 28 18:54:21 2009
@@ -19,17 +19,25 @@
 
 package org.apache.cxf.attachment;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URLDecoder;
 import java.net.URLEncoder;
 import java.util.Collection;
+import java.util.Enumeration;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
 import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.mail.Header;
+import javax.mail.internet.InternetHeaders;
 
 import org.apache.cxf.helpers.HttpHeaderHelper;
 import org.apache.cxf.message.Attachment;
@@ -99,4 +107,59 @@
         }
         return dataHandlers == null ? new LinkedHashMap<String, DataHandler>() : dataHandlers;
     }
+    
+    public static Attachment createAttachment(InputStream stream, InternetHeaders headers) 
+        throws IOException {
+     
+        String id = headers.getHeader("Content-ID", null);
+        if (id != null && id.startsWith("<")) {
+            id = id.substring(1, id.length() - 1);
+        } else {
+            //no Content-ID, set cxf default ID
+            id = "Content-ID: <root.message@cxf.apache.org";
+        }
+
+        id = URLDecoder.decode(id.startsWith("cid:") ? id.substring(4) : id, "UTF-8");
+
+        AttachmentImpl att = new AttachmentImpl(id);
+        
+        final String ct = headers.getHeader("Content-Type", null);
+        
+        boolean quotedPrintable = false;
+        
+        for (Enumeration<?> e = headers.getAllHeaders(); e.hasMoreElements();) {
+            Header header = (Header) e.nextElement();
+            if (header.getName().equalsIgnoreCase("Content-Transfer-Encoding")) {
+                if (header.getValue().equalsIgnoreCase("binary")) {
+                    att.setXOP(true);
+                } else if (header.getValue().equalsIgnoreCase("quoted-printable")) {
+                    quotedPrintable = true;
+                }
+            }
+            att.setHeader(header.getName(), header.getValue());
+        }
+        
+        if (quotedPrintable) {
+            DataSource source = new AttachmentDataSource(ct, new QuotedPrintableDecoderStream(stream));
+            att.setDataHandler(new DataHandler(source));
+        } else {
+            DataSource source = new AttachmentDataSource(ct, stream);
+            att.setDataHandler(new DataHandler(source));
+        }
+        
+        return att;
+    }
+    
+    public static boolean isTypeSupported(String contentType, List<String> types) {
+        if (contentType == null) {
+            return false;
+        }
+        for (String s : types) {
+            if (contentType.indexOf(s) != -1) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
 }

Modified: cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentInInterceptor.java?rev=738583&r1=738582&r2=738583&view=diff
==============================================================================
--- cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentInInterceptor.java (original)
+++ cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentInInterceptor.java Wed Jan 28 18:54:21 2009
@@ -20,9 +20,12 @@
 package org.apache.cxf.interceptor;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 import java.util.logging.Logger;
 
 import org.apache.cxf.attachment.AttachmentDeserializer;
+import org.apache.cxf.attachment.AttachmentUtil;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
@@ -32,6 +35,8 @@
 
     private static final Logger LOG = LogUtils.getL7dLogger(AttachmentInInterceptor.class);
 
+    private static final List<String> TYPES = Collections.singletonList("multipart/related");
+
     /**
      * contruct the soap message with attachments from mime input stream
      * 
@@ -49,8 +54,8 @@
         }
         
         String contentType = (String) message.get(Message.CONTENT_TYPE);
-        if (contentType != null && contentType.toLowerCase().indexOf("multipart/related") != -1) {
-            AttachmentDeserializer ad = new AttachmentDeserializer(message);
+        if (AttachmentUtil.isTypeSupported(contentType, getSupportedTypes())) {
+            AttachmentDeserializer ad = new AttachmentDeserializer(message, getSupportedTypes());
             try {
                 ad.initializeAttachments();
             } catch (IOException e) {
@@ -62,4 +67,7 @@
     public void handleFault(Message messageParam) {
     }
 
+    protected List<String> getSupportedTypes() {
+        return TYPES;
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java?rev=738583&r1=738582&r2=738583&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSBindingFactory.java Wed Jan 28 18:54:21 2009
@@ -23,7 +23,6 @@
 import org.apache.cxf.binding.Binding;
 import org.apache.cxf.binding.xml.XMLBinding;
 import org.apache.cxf.binding.xml.interceptor.XMLFaultOutInterceptor;
-import org.apache.cxf.interceptor.AttachmentInInterceptor;
 import org.apache.cxf.interceptor.StaxOutInterceptor;
 import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor;
 import org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor;
@@ -40,8 +39,6 @@
     public Binding createBinding(BindingInfo bi) {
         XMLBinding binding = new XMLBinding(bi);
 
-        
-        binding.getInInterceptors().add(new AttachmentInInterceptor());
         binding.getInInterceptors().add(new JAXRSInInterceptor());
         
         binding.getOutInterceptors().add(new JAXRSOutInterceptor());

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=738583&r1=738582&r2=738583&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 Wed Jan 28 18:54:21 2009
@@ -35,9 +35,6 @@
  */
 public interface MessageContext {
     
-    String INBOUND_MESSAGE_ATTACHMENTS = "org.apache.cxf.jaxrs.attachments.inbound";
-    String OUTBOUND_MESSAGE_ATTACHMENTS = "org.apache.cxf.jaxrs.attachments.outbound";
-    
     Object get(Object key);
     void put(Object key, Object value);
     

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=738583&r1=738582&r2=738583&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 Jan 28 18:54:21 2009
@@ -18,16 +18,20 @@
  */
 package org.apache.cxf.jaxrs.ext;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Map;
+import java.util.LinkedList;
+import java.util.List;
 
-import javax.activation.DataHandler;
+import javax.mail.internet.InternetHeaders;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.SecurityContext;
@@ -36,9 +40,10 @@
 import javax.ws.rs.ext.Providers;
 
 import org.apache.cxf.attachment.AttachmentUtil;
-import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
+import org.apache.cxf.jaxrs.interceptor.AttachmentInputInterceptor;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
-import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Message;
 
 public class MessageContextImpl implements MessageContext {
@@ -50,8 +55,8 @@
     }
     
     public Object get(Object key) {
-        if (MessageContext.INBOUND_MESSAGE_ATTACHMENTS.equals(key.toString())) {
-            return createAttachments(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
+        if (MultipartBody.INBOUND_MESSAGE_ATTACHMENTS.equals(key.toString())) {
+            return createAttachments(MultipartBody.INBOUND_MESSAGE_ATTACHMENTS);
         }
         return m.get(key);
     }
@@ -111,19 +116,34 @@
         throw new UnsupportedOperationException("MessageContext.put() is not supported yet");
     }
 
-    private Map<String, DataHandler> createAttachments(String propertyName) {
+    private MultipartBody createAttachments(String propertyName) {
         Object o = m.get(propertyName);
         if (o != null) {
-            return CastUtils.cast((Map)o);
+            return (MultipartBody)o;
         }
-        Collection<Attachment> attachments = m.getAttachments();
-        if (attachments == null) {
-            return Collections.emptyMap();
-        }
-        attachments.size();
-        Map<String, DataHandler> dataHandlers = AttachmentUtil.getDHMap(attachments);
-        m.put(propertyName, dataHandlers);
-        return dataHandlers;
+        new AttachmentInputInterceptor().handleMessage(m);
+        
+        List<Attachment> newAttachments = new LinkedList<Attachment>();
+        try {
+            Attachment first = new Attachment(AttachmentUtil.createAttachment(
+                                     m.getContent(InputStream.class), 
+                                     (InternetHeaders)m.get(InternetHeaders.class.getName())));
+            newAttachments.add(first);
+        } catch (IOException ex) {
+            throw new WebApplicationException(500);
+        }
+        
+        Collection<org.apache.cxf.message.Attachment> childAttachments = m.getAttachments();
+        if (childAttachments == null) {
+            childAttachments = Collections.emptyList();
+        }
+        childAttachments.size();
+        for (org.apache.cxf.message.Attachment a : childAttachments) {
+            newAttachments.add(new Attachment(a));
+        }
+        MultipartBody body = new MultipartBody(newAttachments, getHttpHeaders().getMediaType(), false);
+        m.put(propertyName, body);
+        return body;
     }
        
 }

Added: 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=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,109 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+
+public class Attachment {
+
+    private DataHandler handler;
+    private MultivaluedMap<String, String> headers = new MetadataMap<String, String>();
+    private String contentId;
+    
+    public Attachment(org.apache.cxf.message.Attachment a) {
+        handler = a.getDataHandler();
+        contentId = a.getId();
+        for (Iterator<String> i = a.getHeaderNames(); i.hasNext();) {
+            String name = i.next();
+            headers.add(name, a.getHeader(name));
+        }
+    }
+    
+    public Attachment(String id, DataHandler dh, MultivaluedMap<String, String> headers) {
+        handler = dh;
+        contentId = id;
+        this.headers = new MetadataMap<String, String>(headers);
+    }
+    
+    public Attachment(String id, DataSource ds, MultivaluedMap<String, String> headers) {
+        this(id, new DataHandler(ds), headers);
+    }
+    
+    public Attachment(InputStream is, MultivaluedMap<String, String> headers) {
+        this(headers.getFirst("Content-ID"), 
+             new DataHandler(new InputStreamDataSource(is, headers.getFirst("Content-Type"))), 
+             headers);
+    }
+    
+    public ContentDisposition getContentDisposition() {
+        String header = headers.getFirst("Content-Disposition");
+        return header == null ? null : new ContentDisposition(header);
+    }
+
+    public String getContentId() {
+        return contentId;
+    }
+
+    public MediaType getContentType() {
+        String value = handler.getContentType();
+        return value == null ? MediaType.TEXT_PLAIN_TYPE : MediaType.valueOf(value);
+    }
+
+    public DataHandler getDataHandler() {
+        return handler;
+    }
+
+    public String getHeader(String name) {
+        return headers.getFirst(name);
+    }
+    
+    public List<String> getHeaderAsList(String name) {
+        return headers.get(name);
+    }
+
+    public MultivaluedMap<String, String> getHeaders() {
+        return new MetadataMap<String, String>(headers);
+    }
+    
+    @Override
+    public int hashCode() {
+        return contentId.hashCode() + 37 * headers.hashCode(); 
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Attachment)) { 
+            return false;
+        }
+        
+        Attachment other = (Attachment)o;
+        return contentId.equals(other.contentId) && headers.equals(other.headers);
+    }
+    
+
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java?rev=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ContentDisposition {
+
+    private List<String> values;
+    
+    public ContentDisposition(String value) {
+        values = Arrays.asList(value.split(";"));
+    }
+    
+    public String getType() {
+        return values.get(0).trim();
+    }
+    
+    public String getParameter(String name) {
+        for (int i = 1; i < values.size(); i++) {
+            String v = values.get(i).trim();
+            if (v.startsWith(name)) {
+                String[] parts = v.split("=");
+                return parts.length == 2 ? parts[1].trim() : ""; 
+            }
+        }
+        return null;
+    }
+    
+    public Map<String, String> getParameters() {
+        Map<String, String> map = new LinkedHashMap<String, String>();
+        for (int i = 1; i < values.size(); i++) {
+            String[] parts = values.get(i).split("=");
+            map.put(parts[0].trim(), parts.length == 2 ? parts[1].trim() : ""); 
+        }
+        return map;
+    }
+    
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java?rev=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataSource;
+
+public class InputStreamDataSource implements DataSource {
+
+    private InputStream is;
+    private String contentType;
+    private String name;
+    
+    public InputStreamDataSource(InputStream is, String contentType) {
+        this.is = is;
+        this.contentType = contentType;
+    }
+    
+    public InputStreamDataSource(InputStream is, String contentType, String name) {
+        this.is = is;
+        this.contentType = contentType;
+        this.name = name;
+    }
+    
+    public String getContentType() {
+        return contentType;
+    }
+
+    public InputStream getInputStream() throws IOException {
+        return is;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public OutputStream getOutputStream() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/InputStreamDataSource.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java?rev=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.PARAMETER, ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Multipart {
+    String value() default "root";
+    String type() default "*/*";
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Multipart.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 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=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+public class MultipartBody {
+    
+    public static final String INBOUND_MESSAGE_ATTACHMENTS = "org.apache.cxf.jaxrs.attachments.inbound";
+    public static final String OUTBOUND_MESSAGE_ATTACHMENTS = "org.apache.cxf.jaxrs.attachments.outbound";
+    
+    private static final MediaType MULTIPART_RELATED_TYPE = MediaType.valueOf("multipart/related"); 
+    private boolean outbound;
+    private List<Attachment> atts;
+    private MediaType mt; 
+    
+    public MultipartBody(List<Attachment> atts, MediaType mt, boolean outbound) {
+        this.atts = atts;
+        this.outbound = outbound;
+        this.mt = mt == null ? MULTIPART_RELATED_TYPE : mt;
+    }
+    
+    public MultipartBody(List<Attachment> atts, boolean outbound) {
+        this(atts, MULTIPART_RELATED_TYPE, outbound);
+    }
+    
+    public MultipartBody(List<Attachment> atts) {
+        this(atts, MULTIPART_RELATED_TYPE, false);
+    }
+    
+    public MultipartBody(boolean outbound) {
+        this(new ArrayList<Attachment>(), MULTIPART_RELATED_TYPE, outbound);
+    }
+    
+    public MediaType getType() {
+        return mt;
+    }
+    
+    public List<Attachment> getAllAttachments() {
+        
+        return outbound ? atts : Collections.unmodifiableList(atts);
+    }
+    
+    public List<Attachment> getChildAttachments() {
+        List<Attachment> childAtts = new ArrayList<Attachment>();
+        for (int i = 1; i < atts.size(); i++) {
+            childAtts.add(atts.get(i));
+        }
+        return childAtts;
+    }
+    
+    public Attachment getRootAttachment() {
+        return atts.size() > 0 ? atts.get(0) : null;
+    }
+    
+    
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java?rev=738583&r1=738582&r2=738583&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java Wed Jan 28 18:54:21 2009
@@ -68,7 +68,9 @@
     }
 
     public MediaType getMediaType() {
-        return MediaType.valueOf((String)m.get(Message.CONTENT_TYPE));
+        String value = (String)m.get(Message.CONTENT_TYPE);
+        
+        return value == null ? null : MediaType.valueOf(value);
     }
 
     public MultivaluedMap<String, String> getRequestHeaders() {

Added: 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=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.interceptor;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.apache.cxf.interceptor.AttachmentInInterceptor;
+
+public class AttachmentInputInterceptor extends AttachmentInInterceptor {
+    
+    private static final List<String> DEFAULT_TYPES = 
+        Arrays.asList(new String[]{"multipart/related", "multipart/mixed"});
+    
+    private List<String> types = DEFAULT_TYPES;
+    
+    @Override
+    protected List<String> getSupportedTypes() {
+        return types;
+    }
+    
+    @Resource
+    public void setSupportedTypes(List<String> sTypes) {
+        types = sTypes;
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/AttachmentInputInterceptor.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

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=738583&r1=738582&r2=738583&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 Wed Jan 28 18:54:21 2009
@@ -23,6 +23,8 @@
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
@@ -35,11 +37,12 @@
 import javax.ws.rs.ext.Provider;
 
 import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
 import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
-import org.apache.cxf.jaxrs.utils.multipart.MultipartInfo;
 
 @Provider
-@Consumes("multipart/related")
+@Consumes({"multipart/related", "multipart/mixed" })
 public class ActivationProvider implements MessageBodyReader<Object> {
 
     @Context
@@ -47,8 +50,11 @@
     
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, 
                               MediaType mt) {
-        if (DataHandler.class.isAssignableFrom(type) || DataSource.class.isAssignableFrom(type)
-            || (mt.getType().equals("multipart") && mt.getSubtype().equals("related"))) {
+        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")))) {
             return true;
         }
         return false;
@@ -57,21 +63,44 @@
     public Object readFrom(Class<Object> c, Type t, Annotation[] anns, MediaType mt, 
                            MultivaluedMap<String, String> headers, InputStream is) 
         throws IOException, WebApplicationException {
-        MultipartInfo multipart = AttachmentUtils.getMultipart(c, anns, mt, mc, is);
-        if (multipart != null) {
-            if (InputStream.class.isAssignableFrom(multipart.getPart().getClass())) {
-                MessageBodyReader<Object> r = 
-                    mc.getProviders().getMessageBodyReader(c, t, anns, multipart.getType());
-                if (r != null) {
-                    return r.readFrom(c, t, anns, multipart.getType(), headers, 
-                                           (InputStream)multipart.getPart());
-                }
-            } else {
-                // it's either DataSource or DataHandler
-                return multipart.getPart();
+        
+        if (List.class.isAssignableFrom(c)) {
+            Class<?> actual = InjectionUtils.getActualType(t);
+            List<Attachment> infos = AttachmentUtils.getAttachments(mc);
+            if (actual.isAssignableFrom(Attachment.class)) {
+                return infos;
+            }
+            List<Object> objects = new ArrayList<Object>();
+            for (Attachment a : infos) {
+                objects.add(fromAttachment(a, actual, actual, anns));
             }
+            return objects;
+        }
+        
+        Attachment multipart = AttachmentUtils.getMultipart(c, anns, mt, mc);
+        if (multipart != null) {
+            return fromAttachment(multipart, c, t, anns);
         }
         throw new WebApplicationException(404);
     }
     
+    @SuppressWarnings("unchecked")
+    private Object fromAttachment(Attachment multipart, Class<?> c, Type t, Annotation anns[]) 
+        throws IOException {
+        if (DataHandler.class.isAssignableFrom(c)) {
+            return multipart.getDataHandler();
+        } else if (DataSource.class.isAssignableFrom(c)) {
+            return multipart.getDataHandler().getDataSource();
+        } else if (Attachment.class.isAssignableFrom(c)) {
+            return multipart;
+        } else {
+            MessageBodyReader<Object> r = 
+                mc.getProviders().getMessageBodyReader((Class)c, t, anns, multipart.getContentType());
+            if (r != null) {
+                return r.readFrom((Class)c, t, anns, multipart.getContentType(), multipart.getHeaders(), 
+                                  multipart.getDataHandler().getInputStream());
+            }
+        }
+        return 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=738583&r1=738582&r2=738583&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 Jan 28 18:54:21 2009
@@ -20,23 +20,22 @@
 package org.apache.cxf.jaxrs.utils.multipart;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.lang.annotation.Annotation;
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.ResourceBundle;
 import java.util.logging.Logger;
 
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.mail.util.ByteArrayDataSource;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 
 import org.apache.cxf.common.i18n.BundleUtils;
 import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxrs.ext.MessageContext;
-import org.apache.cxf.jaxrs.ext.MultipartID;
+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.AnnotationUtils;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 
@@ -47,67 +46,51 @@
     private AttachmentUtils() {
     }
     
-    public static Map<String, DataHandler> getAttachments(MessageContext mc) {
-        return CastUtils.cast((Map)mc.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS));
+    public static Map<String, Attachment> getChildAttachmentsMap(MessageContext mc) {
+        return fromListToMap(getChildAttachments(mc));
     }
     
-    // TODO : refactor this 'piece'
-    public static MultipartInfo getMultipart(Class<Object> c, Annotation[] anns, 
-         MediaType mt, MessageContext mc, InputStream is) throws IOException {
-        InputStream stream = null;
-        MultipartID id = AnnotationUtils.getAnnotation(anns, MultipartID.class);
+    public static List<Attachment> getChildAttachments(MessageContext mc) {
+        return ((MultipartBody)mc.get(MultipartBody.INBOUND_MESSAGE_ATTACHMENTS)).getChildAttachments();
+    }
+    
+    public static Map<String, Attachment> getAttachmentsMap(MessageContext mc) {
+        return fromListToMap(getAttachments(mc));
+    }
+    
+    public static List<Attachment> getAttachments(MessageContext mc) {
+        return ((MultipartBody)mc.get(MultipartBody.INBOUND_MESSAGE_ATTACHMENTS)).getAllAttachments();
+    }
+    
+    public static Attachment getMultipart(Class<Object> c, Annotation[] anns, 
+        MediaType mt, MessageContext mc) throws IOException {
+        List<Attachment> infos = AttachmentUtils.getAttachments(mc);
+        Multipart id = AnnotationUtils.getAnnotation(anns, Multipart.class);
         if (id != null) {
-            String contentId = id.value();
-            String rootId = mt.getParameters().get("start");
-            if (rootId != null) {
-                rootId = rootId.replace("\"", "").replace("'", "");
-                if (rootId.equalsIgnoreCase(contentId)) {
-                    stream = is;
+            for (Attachment a : getAttachments(mc)) {
+                if (a.getContentId().equals(id.value())) {
+                    checkMediaTypes(a.getContentType(), id.type());
+                    return a;    
                 }
             }
-            if (stream == null) {
-                // TODO: looks like the lazy attachments collection can only be accessed this way
-                for (Map.Entry<String, DataHandler> entry : getAttachments(mc).entrySet()) {
-                    if (entry.getKey().equals(contentId)) {
-                        DataHandler dh = entry.getValue();
-                        MediaType handlerType = dh.getContentType() == null 
-                            ? MediaType.WILDCARD_TYPE : MediaType.valueOf(dh.getContentType());
-                        checkMediaTypes(handlerType, id.type());
-                        Object o =  DataHandler.class.isAssignableFrom(c) ? dh 
-                            : DataSource.class.isAssignableFrom(c) ? dh.getDataSource()
-                            : dh.getInputStream();
-                        return new MultipartInfo(o, handlerType);    
-                    }
-                }
-                org.apache.cxf.common.i18n.Message errorMsg = 
-                    new org.apache.cxf.common.i18n.Message("MULTTIPART_ID_NOT_FOUND", 
-                                                           BUNDLE, 
-                                                           contentId,
-                                                           mt.toString());
-                LOG.warning(errorMsg.toString());
-            }
-        } else {
-            stream = is;
+            org.apache.cxf.common.i18n.Message errorMsg = 
+                new org.apache.cxf.common.i18n.Message("MULTTIPART_ID_NOT_FOUND", 
+                                                       BUNDLE, 
+                                                       id.value(),
+                                                       mt.toString());
+            LOG.warning(errorMsg.toString());
+            
         }
-        if (stream != null) {
-            MediaType partType = MediaType.WILDCARD_TYPE;
-            String ct = mt.getParameters().get("type");
-            if (ct != null) {
-                partType = MediaType.valueOf(ct.replace("\"", "").replace("'", "")); 
-            }
-            if (id != null) {
-                checkMediaTypes(partType, id.type());
-            }
-            if (DataSource.class.isAssignableFrom(c)) {
-                return new MultipartInfo(new ByteArrayDataSource(stream, mt.toString()), partType);
-            } else if (DataHandler.class.isAssignableFrom(c)) {
-                return new MultipartInfo(new DataHandler(new ByteArrayDataSource(stream, mt.toString())),
-                                                         partType);
-            } else {
-                return new MultipartInfo(stream, partType);
-            }
+        
+        return infos.size() > 0 ? infos.get(0) : null; 
+    }
+
+    private static Map<String, Attachment> fromListToMap(List<Attachment> atts) {
+        Map<String, Attachment> map = new LinkedHashMap<String, Attachment>();
+        for (Attachment a : atts) {
+            map.put(a.getContentId(), a);    
         }
-        return null;
+        return map;
     }
     
     private static void checkMediaTypes(MediaType mt1, String mt2) {

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java?rev=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import javax.activation.DataHandler;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AttachmentTest extends Assert {
+
+    
+    @Test
+    public void testGetHeaders() {
+        Attachment a = createAttachment("p1");
+        assertEquals("bar", a.getHeader("foo"));
+    }
+    
+    private Attachment createAttachment(String id) {
+        MetadataMap<String, String> map = new MetadataMap<String, String>();
+        map.add("foo", "bar");
+        return new Attachment(id, 
+                       new DataHandler(new ByteArrayDataSource(new byte[]{1}, "application/octet-stream")),
+                       map);
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/AttachmentTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java?rev=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.ext.multipart;
+
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ContentDispositionTest extends Assert {
+    
+    @Test
+    public void testContentDisposition() {
+        ContentDisposition cd = new ContentDisposition(" attachment ; bar=foo ; baz = baz1");
+        assertEquals("attachment", cd.getType());
+        assertEquals("foo", cd.getParameter("bar"));
+        assertEquals("baz1", cd.getParameter("baz"));
+    }
+    
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/ContentDispositionTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 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=738583&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java Wed Jan 28 18:54:21 2009
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.ext.multipart;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.activation.DataHandler;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MultipartBodyTest extends Assert {
+
+    @Test
+    public void testGetAttachments() {
+        List<Attachment> atts = new ArrayList<Attachment>();
+        atts.add(createAttachment("p1"));
+        atts.add(createAttachment("p2"));
+        MultipartBody b = new MultipartBody(atts);
+        assertEquals(atts, b.getAllAttachments());
+        assertEquals(atts.get(0), b.getRootAttachment());
+        assertEquals(atts.get(1), b.getChildAttachments().get(0));
+    }
+    
+    private Attachment createAttachment(String id) {
+        return new Attachment(id, 
+                       new DataHandler(new ByteArrayDataSource(new byte[]{1}, "application/octet-stream")),
+                       new MetadataMap<String, String>());
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBodyTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

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=738583&r1=738582&r2=738583&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 Wed Jan 28 18:54:21 2009
@@ -37,79 +37,119 @@
     @BeforeClass
     public static void startServers() throws Exception {
         assertTrue("server did not launch correctly",
-                   launchServer(MultipartServer.class));
+                   launchServer(MultipartServer.class, true));
     }
     
     @Test
     public void testBookAsRootAttachmentStreamSource() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/stream";
+        String address = "http://localhost:9085/bookstore/books/stream";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
+    public void testBookAsRootAttachmentStreamSourceNoContentId() throws Exception {
+        String address = "http://localhost:9085/bookstore/books/stream";
+        doAddBook(address, "attachmentData3", 200);               
+    }
+    
+    @Test
     public void testBookAsRootAttachmentInputStream() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/istream";
+        String address = "http://localhost:9085/bookstore/books/istream";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
     public void testBookAsMessageContextDataHandler() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/mchandlers";
+        String address = "http://localhost:9085/bookstore/books/mchandlers";
+        doAddBook(address, "attachmentData", 200);               
+    }
+    
+    @Test
+    public void testBookAsMessageContextAttachments() throws Exception {
+        String address = "http://localhost:9085/bookstore/books/attachments";
+        doAddBook(address, "attachmentData", 200);               
+    }
+    
+    @Test
+    public void testBookAsMessageContextAttachment() throws Exception {
+        String address = "http://localhost:9085/bookstore/books/attachment";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
     public void testAddBookAsRootAttachmentJAXB() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/jaxb";
+        String address = "http://localhost:9085/bookstore/books/jaxb";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
     public void testAddBookAsDataSource() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/dsource";
+        String address = "http://localhost:9085/bookstore/books/dsource";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
     public void testAddBookAsDataSource2() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/dsource2";
+        String address = "http://localhost:9085/bookstore/books/dsource2";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
     public void testAddBookAsJAXB2() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/jaxb2";
+        String address = "http://localhost:9085/bookstore/books/jaxb2";
+        doAddBook(address, "attachmentData", 200);               
+    }
+    
+    @Test
+    public void testAddBookAsListOfAttachments() throws Exception {
+        String address = "http://localhost:9085/bookstore/books/listattachments";
+        doAddBook(address, "attachmentData", 200);               
+    }
+    
+    @Test
+    public void testAddBookAsListOfStreams() throws Exception {
+        String address = "http://localhost:9085/bookstore/books/lististreams";
         doAddBook(address, "attachmentData", 200);               
     }
     
     @Test
     public void testAddBookAsJAXBJSON() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/jaxbjson";
+        String address = "http://localhost:9085/bookstore/books/jaxbjson";
         doAddBook(address, "attachmentData2", 200);               
     }
     
     @Test
+    public void testAddBookAsJAXBJSONMixed() throws Exception {
+        String address = "http://localhost:9085/bookstore/books/jaxbjson";
+        doAddBook("multipart/mixed", address, "attachmentData2", 200);               
+    }
+    
+    @Test
     public void testConsumesMismatch() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/mismatch1";
+        String address = "http://localhost:9085/bookstore/books/mismatch1";
         doAddBook(address, "attachmentData2", 415);               
     }
     
     @Test
     public void testConsumesMismatch2() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/mismatch2";
+        String address = "http://localhost:9085/bookstore/books/mismatch2";
         doAddBook(address, "attachmentData2", 415);               
     }
     
     @Test
     public void testAddBookAsDataHandler() throws Exception {
-        String address = "http://localhost:9080/bookstore/books/dhandler";
+        String address = "http://localhost:9085/bookstore/books/dhandler";
         doAddBook(address, "attachmentData", 200);               
     }
     
     private void doAddBook(String address, String resourceName, int status) throws Exception {
+        doAddBook("multipart/related", address, resourceName, status);
+    }
+    
+    private void doAddBook(String type, String address, String resourceName, int status) throws Exception {
         PostMethod post = new PostMethod(address);
         
-        String ct = "multipart/related; type=\"text/xml\"; " + "start=\"rootPart\"; "
+        String ct = type + "; type=\"text/xml\"; " + "start=\"rootPart\"; "
             + "boundary=\"----=_Part_4_701508.1145579811786\"";
         post.setRequestHeader("Content-Type", ct);
         InputStream is = 

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java?rev=738583&r1=738582&r2=738583&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/MultipartServer.java Wed Jan 28 18:54:21 2009
@@ -31,7 +31,7 @@
         //default lifecycle is per-request, change it to singleton
         sf.setResourceProvider(MultipartStore.class,
                                new SingletonResourceProvider(new MultipartStore()));
-        sf.setAddress("http://localhost:9080/");
+        sf.setAddress("http://localhost:9085/");
 
         sf.create();        
     }

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=738583&r1=738582&r2=738583&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 Wed Jan 28 18:54:21 2009
@@ -21,6 +21,8 @@
 
 
 import java.io.InputStream;
+import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 
 import javax.activation.DataHandler;
@@ -37,7 +39,8 @@
 import javax.xml.transform.stream.StreamSource;
 
 import org.apache.cxf.jaxrs.ext.MessageContext;
-import org.apache.cxf.jaxrs.ext.MultipartID;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
 import org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils;
 
 @Path("/bookstore")
@@ -78,8 +81,8 @@
     @Path("/books/jaxb2")
     @Consumes("multipart/related;type=\"text/xml\"")
     @Produces("text/xml")
-    public Response addBookParts(@MultipartID("rootPart") Book b1,
-                                 @MultipartID("book2") Book b2) 
+    public Response addBookParts(@Multipart("rootPart") Book b1,
+                                 @Multipart("book2") Book b2) 
         throws Exception {
         if (b1.equals(b2)) {
             throw new WebApplicationException();
@@ -95,8 +98,8 @@
     @Path("/books/jaxbjson")
     @Produces("text/xml")
     public Response addBookJaxbJson(
-        @MultipartID(value = "rootPart", type = "text/xml") Book2 b1,
-        @MultipartID(value = "book2", type = "application/json") Book b2) 
+        @Multipart(value = "rootPart", type = "text/xml") Book2 b1,
+        @Multipart(value = "book2", type = "application/json") Book b2) 
         throws Exception {
         if (!"CXF in Action".equals(b1.getName())
             || !"CXF in Action - 2".equals(b2.getName())) {
@@ -109,8 +112,8 @@
     @POST
     @Path("/books/dsource2")
     @Produces("text/xml")
-    public Response addBookFromDataSource2(@MultipartID("rootPart") DataSource ds1,
-                                           @MultipartID("book2") DataSource ds2) 
+    public Response addBookFromDataSource2(@Multipart("rootPart") DataSource ds1,
+                                           @Multipart("book2") DataSource ds2) 
         throws Exception {
         Response r1 = readBookFromInputStream(ds1.getInputStream());
         Response r2 = readBookFromInputStream(ds2.getInputStream());
@@ -126,6 +129,42 @@
     }
     
     @POST
+    @Path("/books/listattachments")
+    @Produces("text/xml")
+    public Response addBookFromListOfAttachments(List<Attachment> atts)  
+        throws Exception {
+        Response r1 = readBookFromInputStream(atts.get(0).getDataHandler().getInputStream());
+        Response r2 = readBookFromInputStream(atts.get(2).getDataHandler().getInputStream());
+        Book b1 = (Book)r1.getEntity();
+        Book b2 = (Book)r2.getEntity();
+        if (b1.equals(b2)) {
+            throw new WebApplicationException();
+        }
+        if (!b1.getName().equals(b2.getName())) {
+            throw new WebApplicationException();
+        }
+        return r1;
+    }
+    
+    @POST
+    @Path("/books/lististreams")
+    @Produces("text/xml")
+    public Response addBookFromListOfStreams(List<InputStream> atts)  
+        throws Exception {
+        Response r1 = readBookFromInputStream(atts.get(0));
+        Response r2 = readBookFromInputStream(atts.get(2));
+        Book b1 = (Book)r1.getEntity();
+        Book b2 = (Book)r2.getEntity();
+        if (b1.equals(b2)) {
+            throw new WebApplicationException();
+        }
+        if (!b1.getName().equals(b2.getName())) {
+            throw new WebApplicationException();
+        }
+        return r1;
+    }
+    
+    @POST
     @Path("/books/dhandler")
     @Produces("text/xml")
     public Response addBookFromDataHandler(DataHandler dh) throws Exception {
@@ -133,13 +172,33 @@
     }
     
     @POST
+    @Path("/books/attachment")
+    @Produces("text/xml")
+    public Response addBookFromAttachment(Attachment a) throws Exception {
+        return readBookFromInputStream(a.getDataHandler().getInputStream());
+    }
+    
+    @POST
     @Path("/books/mchandlers")
     @Produces("text/xml")
     public Response addBookFromMessageContext() throws Exception {
-        Map<String, DataHandler> handlers = AttachmentUtils.getAttachments(context);
-        for (Map.Entry<String, DataHandler> entry : handlers.entrySet()) {
+        Map<String, Attachment> handlers = AttachmentUtils.getAttachmentsMap(context);
+        for (Map.Entry<String, Attachment> entry : handlers.entrySet()) {
             if (entry.getKey().equals("book2")) {
-                return readBookFromInputStream(entry.getValue().getInputStream());
+                return readBookFromInputStream(entry.getValue().getDataHandler().getInputStream());
+            }
+        }
+        throw new WebApplicationException(500);
+    }
+    
+    @POST
+    @Path("/books/attachments")
+    @Produces("text/xml")
+    public Response addBookFromAttachments() throws Exception {
+        Collection<Attachment> handlers = AttachmentUtils.getChildAttachments(context);
+        for (Attachment a : handlers) {
+            if (a.getContentId().equals("book2")) {
+                return readBookFromInputStream(a.getDataHandler().getInputStream());
             }
         }
         throw new WebApplicationException(500);
@@ -164,7 +223,7 @@
     @POST
     @Path("/books/mismatch2")
     @Produces("text/xml")
-    public Response addBookMismatched2(@MultipartID(value = "rootPart", type = "f/b") Book b) {
+    public Response addBookMismatched2(@Multipart(value = "rootPart", type = "f/b") Book b) {
         throw new WebApplicationException();
     }
     

Added: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentData3
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentData3?rev=738583&view=auto
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentData3 (added)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/attachmentData3 Wed Jan 28 18:54:21 2009
@@ -0,0 +1,15 @@
+
+------=_Part_4_701508.1145579811786
+Content-Type: text/xml
+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Book><name>CXF in Action - 2</name></Book>
+------=_Part_4_701508.1145579811786
+Content-Type: image/jpeg
+Content-Transfer-Encoding: binary
+
+foobar
+------=_Part_4_701508.1145579811786--
+Content-Type: application/xml
+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Book><name>CXF in Action - 2</name></Book>
+------=_Part_4_701508.1145579811786--
\ No newline at end of file



Mime
View raw message