You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by da...@apache.org on 2006/11/30 20:19:37 UTC

svn commit: r481043 [1/2] - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/message/ rt/bindings/http/src/test/java/org/apache/cxf/binding/http/ rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/ rt/bindings/soap/src/main/java/org/ap...

Author: dandiep
Date: Thu Nov 30 11:19:29 2006
New Revision: 481043

URL: http://svn.apache.org/viewvc?view=rev&rev=481043
Log:
o Rewrite MTOM support to be completely streamed based. If attachments
  are accessed out of order, they are cached. This is done through a 
  LazyAttachmentCollection. The iterator will iterate over attachments
  as they are accessed, loading them one at a time until the correct
  one is found. On the outgoing side the AttachmentSerializer allows
  us to write out the attachments in steps.
o Move MTOM interceptors into core as they are dependent on SOAP and
  some people would like to use it with XML over HTTP.
o Unify handling of Message.CONTENT_TYPE, transports are now expected
  to deal with it correctly and we shouldn't have to muck with the protocol
  headers to set the content type (like we were doing in 
  OutgoingChainSetupInterceptor).
o Rename some message properties to make it easier for configuration.
o Rewrite server side mtom test to not use the client to make it easy
  to test and debug.
o Remove ugly Message.getAttachmentMimeType() method
o Try to use IOUtils.copy() in more places to reduce duplication
o This has not been interop tested. I think there may be an issue or two
  when using with .NET 2.0, but I need to test and track down the issue
  (will do so soon).

Added:
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/
      - copied from r480652, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java
      - copied, changed from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java   (with props)
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java   (with props)
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java   (with props)
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java   (with props)
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java
      - copied, changed from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java
      - copied, changed from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/Data.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/EchoService.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/MtomServerTest.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/request   (with props)
Removed:
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java
    incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/attachments/
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/ServerMtomXopTest.java
Modified:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java
    incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java
    incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java
    incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java
    incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java
    incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFTest.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBDataBinding.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/attachment/JAXBAttachmentMarshaller.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/attachment/JAXBAttachmentUnmarshaller.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/MessageDataReader.java
    incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
    incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/JettyHTTPDestination.java
    incubator/cxf/trunk/rt/transports/local/src/main/java/org/apache/cxf/transport/local/LocalConduit.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/TestAttachmentOutInterceptor.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/mtom/TestMultipartMessageInterceptor.java

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/AbstractWrappedMessage.java Thu Nov 30 11:19:29 2006
@@ -68,10 +68,18 @@
         return message.getAttachments();
     }
 
-    public String getAttachmentMimeType() {
-        return message.getAttachmentMimeType();
+    public void setAttachments(Collection<Attachment> attachments) {
+        message.setAttachments(attachments);
     }
-    
+
+    public Message getMessage() {
+        return message;
+    }
+
+    public void setMessage(Message message) {
+        this.message = message;
+    }
+
     public Conduit getConduit() {
         return message.getConduit();
     }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java Thu Nov 30 11:19:29 2006
@@ -45,10 +45,10 @@
     String HTTP_REQUEST_METHOD = Message.class.getName() + ".HTTP_REQUEST_METHOD";
     String PATH_INFO = Message.class.getName() + ".PATH_INFO";
     String QUERY_STRING = Message.class.getName() + ".QUERY_STRING";
-    String MTOM_ENABLED = Message.class.getName() + ".isMtomEnabled";
+    String MTOM_ENABLED = "mtom-enabled";
     String SCHEMA_VALIDATION_ENABLED = Message.class.getCanonicalName() + ".schemaValidationEnabled";
     String FAULT_STACKTRACE_ENABLED = "faultStackTraceEnabled";
-    String CONTENT_TYPE = Message.class.getName() + ".ContentType";
+    String CONTENT_TYPE = "Content-Type";
     String BASE_PATH = Message.class.getName() + ".BASE_PATH";
     String ENCODING = Message.class.getName() + ".ENCODING";
     String FIXED_PARAMETER_ORDER = Message.class.getName() + "FIXED_PARAMETER_ORDER";
@@ -75,11 +75,8 @@
     
     Collection<Attachment> getAttachments();
 
-    /**
-     * @return the mime type string  
-     */
-    String getAttachmentMimeType();
-
+    void setAttachments(Collection<Attachment> attachments);
+    
     /**
      * Retrieve the encapsulated content as a particular type (a result type
      * if message is outbound, a source type if message is inbound)

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageImpl.java Thu Nov 30 11:19:29 2006
@@ -19,10 +19,8 @@
 
 package org.apache.cxf.message;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -34,7 +32,7 @@
 import org.apache.cxf.transport.Destination;
 
 public class MessageImpl extends HashMap<String, Object> implements Message {
-    private List<Attachment> attachments = new ArrayList<Attachment>();
+    private Collection<Attachment> attachments;
     private Conduit conduit;
     private Destination destination;
     private Exchange exchange;
@@ -44,6 +42,10 @@
     
     public Collection<Attachment> getAttachments() {
         return attachments;
+    }
+
+    public void setAttachments(Collection<Attachment> attachments) {
+        this.attachments = attachments;
     }
 
     public String getAttachmentMimeType() {

Modified: incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/http/src/test/java/org/apache/cxf/binding/http/AbstractRestTest.java Thu Nov 30 11:19:29 2006
@@ -36,6 +36,7 @@
 import org.apache.cxf.BusException;
 import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.test.AbstractCXFTest;
 
 public abstract class AbstractRestTest extends AbstractCXFTest {
@@ -91,8 +92,10 @@
         InputStream msgIs = getResourceAsStream(message);
         assertNotNull(msgIs);
 
-        copy(msgIs, out);
-
+        IOUtils.copy(msgIs, out);
+        out.close();
+        msgIs.close();
+        
         InputStream is = c.getInputStream();
         Document res = DOMUtils.readXml(is);
         

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap11.java Thu Nov 30 11:19:29 2006
@@ -60,11 +60,7 @@
     public static Soap11 getInstance() {
         return INSTANCE;
     }
-
-    public String getSoapMimeType() {
-        return "\"text/xml\"; charset=utf-8";
-    }
-
+    
     public double getVersion() {
         return version;
     }

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/Soap12.java Thu Nov 30 11:19:29 2006
@@ -42,7 +42,6 @@
     private final String ultimateReceiverRole = namespace + "/role/ultimateReceiver";
 
     private final String nextRole = namespace + "/role/next";
-    
 
     private final String soapEncodingStyle = "http://www.w3.org/2003/05/soap-encoding";
 
@@ -62,10 +61,6 @@
         return instance;
     }
 
-    public String getSoapMimeType() {
-        return "\"application/soap+xml\"; charset=utf-8";
-    }
-    
     public double getVersion() {
         return version;
     }

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBinding.java Thu Nov 30 11:19:29 2006
@@ -49,8 +49,10 @@
         SoapMessage soapMessage = new SoapMessage(m);
         soapMessage.setVersion(version);
 
-        soapMessage.put(Message.CONTENT_TYPE, version.getContentType());
-
+        if (!soapMessage.containsKey(Message.CONTENT_TYPE)) {
+            soapMessage.put(Message.CONTENT_TYPE, version.getContentType());
+        }
+        
         return soapMessage;
     }
 

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapBindingFactory.java Thu Nov 30 11:19:29 2006
@@ -39,8 +39,6 @@
 import org.apache.cxf.binding.AbstractBindingFactory;
 import org.apache.cxf.binding.Binding;
 import org.apache.cxf.binding.BindingFactoryManager;
-import org.apache.cxf.binding.soap.interceptor.AttachmentOutInterceptor;
-import org.apache.cxf.binding.soap.interceptor.MultipartMessageInterceptor;
 import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
 import org.apache.cxf.binding.soap.interceptor.RPCInInterceptor;
 import org.apache.cxf.binding.soap.interceptor.RPCOutInterceptor;
@@ -57,8 +55,10 @@
 import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
 import org.apache.cxf.binding.soap.model.SoapOperationInfo;
 import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.interceptor.AttachmentOutInterceptor;
 import org.apache.cxf.interceptor.BareInInterceptor;
 import org.apache.cxf.interceptor.BareOutInterceptor;
+import org.apache.cxf.interceptor.MultipartMessageInterceptor;
 import org.apache.cxf.interceptor.StaxInInterceptor;
 import org.apache.cxf.interceptor.StaxOutInterceptor;
 import org.apache.cxf.interceptor.URIMappingInterceptor;

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapMessage.java Thu Nov 30 11:19:29 2006
@@ -72,9 +72,4 @@
     public <T> void setHeaders(Class<T> format, T content) {
         headers.put(format, content);
     }
-    
-    public String getAttachmentMimeType() {
-        return version.getSoapMimeType();
-    }
-    
 }

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapVersion.java Thu Nov 30 11:19:29 2006
@@ -64,7 +64,5 @@
 
     String getNextRole();
     
-    String getSoapMimeType();
-    
     String getContentType();
 }

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapPreProtocolOutInterceptor.java Thu Nov 30 11:19:29 2006
@@ -22,16 +22,15 @@
 import java.util.HashMap;
 import java.util.List;
 
-
 import org.apache.cxf.binding.soap.Soap11;
 import org.apache.cxf.binding.soap.SoapMessage;
 import org.apache.cxf.binding.soap.SoapVersion;
+import org.apache.cxf.interceptor.AttachmentOutInterceptor;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.phase.Phase;
 
 import static org.apache.cxf.message.Message.MIME_HEADERS;
 
-
 /**
  * This interceptor is responsible for setting up the SOAP version
  * and header, so that this is available to any pre-protocol interceptors
@@ -41,7 +40,8 @@
 
     public SoapPreProtocolOutInterceptor() {
         super();
-        setPhase(Phase.PRE_PROTOCOL);
+        setPhase(Phase.PRE_STREAM);
+        getBefore().add(AttachmentOutInterceptor.class.getName());
     }
 
     /**

Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/MustUnderstandInterceptorTest.java Thu Nov 30 11:19:29 2006
@@ -29,8 +29,8 @@
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamReader;
 
-import org.apache.cxf.binding.attachment.AttachmentImpl;
-import org.apache.cxf.binding.attachment.AttachmentUtil;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.AttachmentUtil;
 import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
 import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
 import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;

Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/ReadHeaderInterceptorTest.java Thu Nov 30 11:19:29 2006
@@ -30,8 +30,8 @@
 
 import org.w3c.dom.Element;
 
-import org.apache.cxf.binding.attachment.AttachmentImpl;
-import org.apache.cxf.binding.attachment.AttachmentUtil;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.AttachmentUtil;
 import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;
 import org.apache.cxf.interceptor.StaxInInterceptor;
 import org.apache.cxf.message.Attachment;

Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/SoapBindingTest.java Thu Nov 30 11:19:29 2006
@@ -38,6 +38,8 @@
 
         assertEquals("text/xml", soapMessage.get(Message.CONTENT_TYPE));
         
+        soapMessage.remove(Message.CONTENT_TYPE);
+        
         sb.setSoapVersion(Soap12.getInstance());
         soapMessage = (SoapMessage) sb.createMessage(soapMessage);
         assertEquals(Soap12.getInstance(), soapMessage.getVersion());     

Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestUtil.java Thu Nov 30 11:19:29 2006
@@ -23,13 +23,14 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Collection;
 
 import javax.activation.DataHandler;
 import javax.mail.util.ByteArrayDataSource;
 
-import org.apache.cxf.binding.attachment.AttachmentImpl;
-import org.apache.cxf.binding.attachment.AttachmentUtil;
+import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.attachment.AttachmentUtil;
 import org.apache.cxf.interceptor.InterceptorChain;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Exchange;
@@ -70,7 +71,8 @@
         soapMessage.setContent(Attachment.class, new AttachmentImpl(cid, new DataHandler(bads)));
 
         // setup the message attachments
-        Collection<Attachment> attachments = soapMessage.getAttachments();
+        Collection<Attachment> attachments = new ArrayList<Attachment>();
+        soapMessage.setAttachments(attachments);
 //        String cidAtt1 = "cid:http://cxf.apache.org/me.bmp";
 //        bads = new ByteArrayDataSource(clazz.getResourceAsStream("me.bmp"), "image/bmp");
 //        AttachmentImpl att1 = new AttachmentImpl(cidAtt1, new DataHandler(bads));

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDataSource.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDataSource.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -29,12 +29,7 @@
 
     private final String ct;
     private final InputStream in;
-
-    public AttachmentDataSource(String ctParam, CachedOutputStream cosParam) throws IOException {
-        this.ct = ctParam;
-        this.in = cosParam.getInputStream();
-    }
-
+    
     public AttachmentDataSource(String ctParam, InputStream inParam) {
         this.ct = ctParam;
         this.in = inParam;

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentDeserializer.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java Thu Nov 30 11:19:29 2006
@@ -17,33 +17,23 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PushbackInputStream;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
-
 import javax.mail.Header;
 import javax.mail.MessagingException;
 import javax.mail.internet.InternetHeaders;
 
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.helpers.HttpHeaderHelper;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Message;
 
-
 public class AttachmentDeserializer {
 
     public static final String ATTACHMENT_DIRECTORY = "attachment-directory";
@@ -52,139 +42,129 @@
 
     public static final int THRESHHOLD = 1024 * 100;
 
+    private boolean lazyLoading = true;
+    
     private PushbackInputStream stream;
 
     private String boundary;
 
     private String contentType;
 
-    private List<CachedOutputStream> cache;
+    private LazyAttachmentCollection attachments;
 
     private Message message;
 
-    public AttachmentDeserializer(Message messageParam) {
-        message = messageParam;
-    }
+    private InputStream body;
 
-    
-    public boolean preprocessMessage() {
-        InputStream input;
-        Map<String, List<String>> httpHeaders;
-        // processing message if its multi-part/form-related
-        try {
-            httpHeaders = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
-            if (httpHeaders == null) {
-                return false;
-            } else {
-                List ctList = (List) HttpHeaderHelper.getHeader(httpHeaders, HttpHeaderHelper.CONTENT_TYPE);
-                if (ctList != null) {
-                    for (int x = 0; x < ctList.size(); x++) {
-                        if (x == 0) {
-                            contentType = (String) ctList.get(x);
-                        } else {
-                            contentType += "; " + (String) ctList.get(x);
-                        }
-                    }
-                }
-                if (contentType == null) { 
-                    return false;
-                }
-                input = message.getContent(InputStream.class);
-                if (input == null) {
-                    return false;
-                }
-            }
-            //printStream(input);
-            if (contentType.toLowerCase().indexOf("multipart/related") != -1) {
-                cache = new ArrayList<CachedOutputStream>();
-                int i = contentType.indexOf("boundary=\"");
-                int end;
-                int len;
-                if (i == -1) {
-                    i = contentType.indexOf("boundary=");
-                    end = contentType.indexOf(";", i + 9);
-                    if (end == -1) {
-                        end = contentType.length();
-                    }
-                    len = 9;
-                } else {
-                    end = contentType.indexOf("\"", i + 10);
-                    len = 10;
-                }
-                if (i == -1 || end == -1) {
-                    throw new IOException("Invalid content type: missing boundary! " + contentType);
-                }
-                boundary = "--" + contentType.substring(i + len, end);
-                stream = new PushbackInputStream(input, boundary.length());
-                if (!readTillFirstBoundary(stream, boundary.getBytes())) {
-                    throw new IOException("Couldn't find MIME boundary: " + boundary);
-                }
-                processSoapBody();
-                return true;
-            }
-        } catch (IOException ioe) {
-            message.setContent(Exception.class, ioe);
-        } catch (MessagingException me) {
-            message.setContent(Exception.class, me);
-        }
-        return false;
+    public AttachmentDeserializer(Message message) {
+        this.message = message;
     }
 
-    /**
-     * release the resource
-     */
-    public void dispose() {
-        if (cache != null) {
-            for (CachedOutputStream cos : cache) {
-                cos.dispose();
-            }
-        }
+    public void initializeAttachments() throws IOException {
+        initializeRootMessage();
+        
+        attachments = new LazyAttachmentCollection(this);
+        message.setAttachments(attachments);
     }
 
-    public void process() throws MessagingException, IOException {
-        processSoapBody();
-        processAttachments();
-    }
+    protected void initializeRootMessage() throws IOException {
+        contentType = (String) message.get(Message.CONTENT_TYPE);
 
-    /**
-     * construct the primary soap body part and attachments
-     */
-    public void processSoapBody() throws MessagingException, IOException {
+        if (contentType == null) { 
+            throw new IllegalStateException("Content-Type can not be empty!");
+        }
+        
+        InputStream input = message.getContent(InputStream.class);
+        if (input == null) {
+            throw new IllegalStateException("An InputStream must be provided!");
+        }
 
-        Attachment soapMimePart = readMimePart();
-        message.setContent(Attachment.class, soapMimePart);        
-        InputStream in = soapMimePart.getDataHandler().getInputStream();
-        message.setContent(InputStream.class, in);
-    }
+        if (contentType.toLowerCase().indexOf("multipart/related") != -1) {
+            int i = contentType.indexOf("boundary=\"");
+            int end;
+            int len;
+            if (i == -1) {
+                i = contentType.indexOf("boundary=");
+                end = contentType.indexOf(";", i + 9);
+                if (end == -1) {
+                    end = contentType.length();
+                }
+                len = 9;
+            } else {
+                end = contentType.indexOf("\"", i + 10);
+                len = 10;
+            }
+            if (i == -1 || end == -1) {
+                throw new IOException("Invalid content type: missing boundary! " + contentType);
+            }
+            boundary = "--" + contentType.substring(i + len, end);
+            stream = new PushbackInputStream(input, boundary.length());
+            if (!readTillFirstBoundary(stream, boundary.getBytes())) {
+                throw new IOException("Couldn't find MIME boundary: " + boundary);
+            }
 
-    public void processAttachments() throws MessagingException, IOException {
-        Collection<Attachment> attachments = message.getAttachments();
-        Attachment att = readMimePart();
-        while (att != null && att.getId() != null) {
-            attachments.add(att);
-            att = readMimePart();
+            try {
+                // TODO: Do we need to copy these headers somewhere?
+                new InternetHeaders(stream);
+            } catch (MessagingException e) {
+                throw new RuntimeException(e);
+            }
+            
+            body = new DelegatingInputStream(new MimeBodyPartInputStream(stream, boundary.getBytes()));
+            message.setContent(InputStream.class, body);
         }
     }
 
-    public Attachment getAttachment(String cid) throws MessagingException, IOException {
-        Collection<Attachment> attachments = message.getAttachments();
-        for (Attachment att : attachments) {
-            if (att.getId().equals(cid)) {
-                return att;
-            }
+    public AttachmentImpl readNext() throws IOException {
+        // Cache any mime parts that are currently being streamed
+        cacheStreamedAttachments();
+        
+        int v = stream.read();
+        if (v == -1) {
+            return null;
         }
-        Attachment att = readMimePart();
-        while (att != null && att.getId() != null) {
-            attachments.add(att);
-            String convertId = cid.substring(0, 4).equals("cid:") ? cid.substring(4) : cid;
-            if (att.getId().equals(convertId)) {
-                return att;
-            }
-            att = readMimePart();
+        stream.unread(v);
+        
+        
+        InternetHeaders headers;
+        try {
+            headers = new InternetHeaders(stream);
+        } catch (MessagingException e) {
+            // TODO create custom IOException
+            throw new RuntimeException(e);
+        }
+        
+        String id = headers.getHeader("Content-ID", null);
+        if (id != null && id.startsWith("<")) {
+            id = id.substring(1, id.length() - 1);
+        }
+        id = id.startsWith("cid:") ? id.substring(4) : id;
+        
+        AttachmentImpl att = new AttachmentImpl(id);
+        setupAttachment(att, headers);
+        return att;
+    }
+    
+    private void cacheStreamedAttachments() throws IOException {
+        if (body instanceof DelegatingInputStream 
+            && !((DelegatingInputStream) body).isClosed()) {
+            
+            cache((DelegatingInputStream) body, true);
+            message.setContent(InputStream.class, body);
+        }
+        
+        for (Attachment a : attachments.getLoadedAttachments()) {
+            DataSource s = a.getDataHandler().getDataSource();
+            cache((DelegatingInputStream) s.getInputStream(), false);
         }
-        return null;
     }
 
+    private void cache(DelegatingInputStream input, boolean deleteOnClose) throws IOException {
+        CachedOutputStream out = new CachedOutputStream();
+        IOUtils.copy(input, out);
+        input.setInputStream(out.getInputStream());
+    }
+    
     /**
      * Move the read pointer to the begining of the first part read till the end
      * of first boundary
@@ -222,142 +202,35 @@
         return false;
     }
 
-    private Attachment readMimePart() throws MessagingException, IOException {
-
-        int v = stream.read();
-        if (v == -1) {
-            return null;
-        }
-        stream.unread(v);
-        InternetHeaders iheaders = new InternetHeaders(stream);
-        Map<String, List<String>> internalHeaders = new HashMap<String, List<String>>(); 
-        for (Enumeration e = iheaders.getAllHeaders(); e.hasMoreElements();) {
-            Header header = (Header)e.nextElement();            
-            List<String> values = new ArrayList<String>();
-            String headerName = HttpHeaderHelper.getHeaderKey(header.getName());
-            internalHeaders.put(headerName, values);
-            values.add(header.getValue());
-        }
+    /**
+     * Create an Attachment from the MIME stream. If there is a previous attachment
+     * that is not read, cache that attachment.
+     * 
+     * @return
+     * @throws IOException
+     */
+    private void setupAttachment(AttachmentImpl att, InternetHeaders headers) throws IOException {
         MimeBodyPartInputStream partStream = new MimeBodyPartInputStream(stream, boundary.getBytes());
-        final CachedOutputStream cos = new CachedOutputStream();
-        cos.setThreshold(THRESHHOLD);
-        AbstractCachedOutputStream.copyStream(partStream, cos, THRESHHOLD);
-        cos.close();        
-        final String ct = constructHeaderValue(HttpHeaderHelper.getHeader(internalHeaders, 
-                HttpHeaderHelper.CONTENT_TYPE));
-        cache.add(cos);
-        DataSource source = new AttachmentDataSource(ct, cos);
-        DataHandler dh = new DataHandler(source);
-        String id = internalHeaders.get(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_ID)).get(0);
-        if (id != null && id.startsWith("<")) {
-            id = id.substring(1, id.length() - 1);
-        }
-        AttachmentImpl att = new AttachmentImpl(id, dh);
-        for (Iterator<String> it = internalHeaders.keySet().iterator(); it.hasNext();) {
-            String headerName = it.next();
-            List values = internalHeaders.get(headerName);
-            if (headerName.equalsIgnoreCase("Content-Transfer-Encoding")
-                            && values.size() == 1 && values.get(0).equals("binary")) {
+        
+        final String ct = headers.getHeader("Content-Type", null);
+        DataSource source = new AttachmentDataSource(ct, new DelegatingInputStream(partStream));
+        att.setDataHandler(new DataHandler(source));
+        
+        for (Enumeration<?> e = headers.getAllHeaders(); e.hasMoreElements();) {
+            Header header = (Header) e.nextElement();
+            if (header.getName().equalsIgnoreCase("Content-Transfer-Encoding")
+                            && header.getValue().equalsIgnoreCase("binary")) {
                 att.setXOP(true);
             }
-            att.setHeader(headerName, constructHeaderValue(values));
+            att.setHeader(header.getName(), header.getValue());
         }
-        return att;
     }
 
-    private static String constructHeaderValue(List values) {
-        StringBuffer sb = new StringBuffer(200);
-        for (int i = 0; i < values.size(); i++) {
-            sb.append(values.get(i));
-        }
-        return sb.toString();
+    public boolean isLazyLoading() {
+        return lazyLoading;
     }
-    
-    private class MimeBodyPartInputStream extends InputStream {
-
-        PushbackInputStream inStream;
-
-        boolean boundaryFound;
-
-        byte[] boundary;
-
-        public MimeBodyPartInputStream(PushbackInputStream inStreamParam, byte[] boundaryParam) {
-            super();
-            this.inStream = inStreamParam;
-            this.boundary = boundaryParam;
-        }
 
-        public int read() throws IOException {
-            boolean needUnread0d0a = false;
-            if (boundaryFound) {
-                return -1;
-            }
-
-            // read the next value from stream
-            int value = inStream.read();
-            // A problem occured because all the mime parts tends to have a /r/n
-            // at the end. Making it hard to transform them to correct
-            // DataSources.
-            // This logic introduced to handle it
-            if (value == 13) {
-                value = inStream.read();
-                if (value != 10) {
-                    inStream.unread(value);
-                    return 13;
-                } else {
-                    value = inStream.read();
-                    if ((byte) value != boundary[0]) {
-                        inStream.unread(value);
-                        inStream.unread(10);
-                        return 13;
-                    } else {
-                        needUnread0d0a = true;
-                    }
-                }
-            } else if ((byte) value != boundary[0]) {
-                return value;
-            }
-            // read value is the first byte of the boundary. Start matching the
-            // next characters to find a boundary
-            int boundaryIndex = 0;
-            while ((boundaryIndex < boundary.length) && ((byte) value == boundary[boundaryIndex])) {
-                value = inStream.read();
-                boundaryIndex++;
-            }
-            if (boundaryIndex == boundary.length) {
-                // boundary found
-                boundaryFound = true;
-                // read the end of line character
-                if (inStream.read() == 45 && value == 45) {
-                    // Last mime boundary should have a succeeding "--"
-                    // as we are on it, read the terminating CRLF
-                    inStream.read();
-                    inStream.read();
-                }
-                return -1;
-            }
-            // Boundary not found. Restoring bytes skipped.
-            // write first skipped byte, push back the rest
-            if (value != -1) {
-                // Stream might have ended
-                inStream.unread(value);
-            }
-            if (needUnread0d0a) {
-                inStream.unread(boundary, 0, boundaryIndex);
-                inStream.unread(10);
-                value = 13;
-            } else {
-                inStream.unread(boundary, 1, boundaryIndex - 1);                
-                value = boundary[0];
-            }
-            return value;
-        }
-    }
-
-    protected static void printStream(InputStream in) throws IOException {
-        for (int i = in.read(); i != -1; i = in.read()) {
-            System.out.write(i);
-        }
-        System.out.println("print stream");
+    public void setLazyLoading(boolean lazyLoading) {
+        this.lazyLoading = lazyLoading;
     }
 }

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentImpl.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentImpl.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
 import java.util.HashMap;
 import java.util.Iterator;
@@ -29,14 +29,18 @@
 
 public class AttachmentImpl implements Attachment {
 
-    private DataHandler handler;
+    private DataHandler dataHandler;
     private String id;
     private Map<String, String> headers = new HashMap<String, String>();
     private boolean xop;
 
+    public AttachmentImpl(String idParam) {
+        this.id = idParam;
+    }
+    
     public AttachmentImpl(String idParam, DataHandler handlerParam) {
         this.id = idParam;
-        this.handler = handlerParam;
+        this.dataHandler = handlerParam;
     }
 
     public String getId() {
@@ -44,7 +48,11 @@
     }
 
     public DataHandler getDataHandler() {
-        return handler;
+        return dataHandler;
+    }
+
+    public void setDataHandler(DataHandler dataHandler) {
+        this.dataHandler = dataHandler;
     }
 
     public void setHeader(String name, String value) {

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentSerializer.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java Thu Nov 30 11:19:29 2006
@@ -17,101 +17,100 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
-import java.io.InputStream;
-import java.io.ObjectOutputStream;
+import java.io.IOException;
 import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.helpers.HttpHeaderHelper;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Message;
 
 
 public class AttachmentSerializer {
 
+    private static final String BODY_ATTACHMENT_ID = "root.message@cxf.apache.org";
     private Message message;
-
-    private InputStream in;
-
+    private String bodyBoundary;
+    private OutputStreamWriter writer;
     private OutputStream out;
-
-    public AttachmentSerializer(Message messageParam, InputStream inParam, OutputStream outParam) {
+    
+    public AttachmentSerializer(Message messageParam) {
         message = messageParam;
-        in = inParam;
-        out = outParam;
     }
 
     /**
-     * Using result in soapMessage & attachment to write to output stream
-     * 
-     * @param soapMessage
-     * @param in
-     *            input stream contain the attachment
-     * @param out
-     * @throws CxfRioException
+     * Serialize the beginning of the attachment which includes the MIME 
+     * beginning and headers for the root message.
      */
+    public void writeProlog() throws IOException {
+        // Create boundary for body
+        bodyBoundary = AttachmentUtil.getUniqueBoundaryValue(0);
+        
+        String bodyCt = (String) message.get(Message.CONTENT_TYPE);
+        
+        // Set transport mime type
+        StringBuilder ct = new StringBuilder();
+        ct.append("multipart/related; boundary=\"")
+            .append(bodyBoundary)
+            .append("\"; ")
+            .append("type=\"application/xop+xml\"; ")
+            .append("start=\"<")
+            .append(BODY_ATTACHMENT_ID)
+            .append(">\"; ")
+            .append("start-info=\"")
+            .append(bodyCt)
+            .append("\"");
+        
+        message.put(Message.CONTENT_TYPE, ct.toString());
+
+        // 2. write headers
+        out = message.getContent(OutputStream.class);
+        String encoding = (String) message.get(Message.ENCODING);
+        if (encoding == null) {
+            encoding = "UTF-8";
+        }
+        writer = new OutputStreamWriter(out, encoding);
+        writer.write("--");
+        writer.write(bodyBoundary);
+        
+        writeHeaders(bodyCt, BODY_ATTACHMENT_ID);
+    }
 
-    public String serializeMultipartMessage() {
+    private void writeHeaders(String contentType, String attachmentId) throws IOException {
+        writer.write("\n");
+        writer.write("Content-Type: ");
+        writer.write(contentType);
+        writer.write("\n");
+
+        writer.write("Content-Transfer-Encoding: binary\n");
+
+        writer.write("Content-ID: <");
+        writer.write(attachmentId);
+        writer.write(">\n\n");
+        writer.flush();
+    }
 
-        String soapPartId;
-        String boundary = AttachmentUtil.getUniqueBoundaryValue(0);
-        try {
-            soapPartId = AttachmentUtil.createContentID(null);
-        } catch (UnsupportedEncodingException e) {
-            throw new Fault(e);
-        }
-        try {
-            Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>) message
-                            .get(Message.PROTOCOL_HEADERS));
-            if (headers == null) {
-                // this is the case of server out (response)
-                headers = new HashMap<String, List<String>>();
-                message.put(Message.PROTOCOL_HEADERS, headers);
-            }
-            AttachmentUtil.setMimeRequestHeader(headers, message, soapPartId,
-                            "soap message with attachments", boundary);
-            //finish prepare header, call flush to flush headers and resetOut to get wire stream
-            out.flush();
+    /**
+     * Write the end of the body boundary and any attachments included.
+     * @throws IOException
+     */
+    public void writeAttachments() throws IOException {
+        writer.write('\n');
+        writer.write("--");
+        writer.write(bodyBoundary);
+     
+        for (Attachment a : message.getAttachments()) {
+            writeHeaders(a.getDataHandler().getContentType(), a.getId());
+            
+            IOUtils.copy(a.getDataHandler().getInputStream(), out);
             
-            String soapHeader = AttachmentUtil.getSoapPartHeader(message, soapPartId, "");
-            out.write(("--" + boundary + "\r\n").getBytes());
-            out.write(soapHeader.getBytes());                                   
-            AbstractCachedOutputStream.copyStream(in, out, 64 * 1024);
-            for (Attachment att : message.getAttachments()) {
-                soapHeader = AttachmentUtil.getAttchmentPartHeader(att);
-                out.write(("--" + boundary + "\r\n").getBytes());
-                out.write(soapHeader.getBytes());                
-                Object content = att.getDataHandler().getContent();
-                if (content instanceof InputStream) {
-                    InputStream insAtt = (InputStream) content;
-                    AbstractCachedOutputStream.copyStream(insAtt, out, 64 * 1024);
-                } else {                    
-                    ObjectOutputStream oos = new ObjectOutputStream(out);
-                    oos.writeObject(content);
-                }
-                out.write("\r\n".getBytes());
-            }
-            out.write(("--" + boundary + "--\r\n").getBytes());
-            out.flush();            
-            // build contentType string for return
-            List<String> contentType = (List<String>) headers.get(HttpHeaderHelper.getHeaderKey(
-                    HttpHeaderHelper.CONTENT_TYPE));
-            StringBuffer sb = new StringBuffer(120);
-            for (String s : contentType) {
-                sb.append(s);
-            }
-            return sb.toString();
-        } catch (Exception e) {
-            throw new Fault(e);
+            writer.write("--");
+            writer.write(bodyBoundary);
+            writer.write('\n');
         }
-
+        
+        writer.flush();
     }
 }

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/AttachmentUtil.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java Thu Nov 30 11:19:29 2006
@@ -17,21 +17,17 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
 import org.apache.cxf.helpers.HttpHeaderHelper;
 import org.apache.cxf.message.Attachment;
-import org.apache.cxf.message.Message;
 
 public final class AttachmentUtil {
 
@@ -70,21 +66,6 @@
         return s.toString();
     }
 
-    public static String getSoapPartHeader(Message message, String soapPartId, String action) {
-        StringBuffer buffer = new StringBuffer(200);
-        buffer.append(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_TYPE)
-                + ": application/xop+xml; charset=utf-8; ");
-        buffer.append("type=\"" + message.getAttachmentMimeType());
-        if (action != null) {
-            buffer.append("; action=" + action + "\"\r\n");
-        } else {
-            buffer.append("\"\r\n");
-        }
-        buffer.append("Content-Transfer-Encoding: binary\r\n");
-        buffer.append("Content-ID: <" + soapPartId + ">\r\n\r\n");
-        return buffer.toString();
-    }
-
     public static String getAttchmentPartHeader(Attachment att) {
         StringBuffer buffer = new StringBuffer(200);
         buffer.append(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_TYPE) + ": "
@@ -96,26 +77,4 @@
         return buffer.toString();
     }
 
-    public static void setMimeRequestHeader(Map<String, List<String>> reqHeaders, Message message,
-            String soapPartId, String contentDesc, String boundary) {
-        List<String> header1 = new ArrayList<String>();
-        header1.add("1.0");
-        reqHeaders.put("MIME-Version", header1);
-        List<String> header2 = new ArrayList<String>();
-        header2.add("Multipart/" + getMimeSubType(message, soapPartId, boundary));
-        reqHeaders.put(HttpHeaderHelper.getHeaderKey(HttpHeaderHelper.CONTENT_TYPE), header2);
-        List<String> header3 = new ArrayList<String>();
-        header3.add(contentDesc);
-        reqHeaders.put("Content-Description", header3);
-
-    }
-
-    public static String getMimeSubType(Message message, String soapPartId, String boundary) {
-        StringBuffer ct = new StringBuffer();
-        ct.append("related; boundary=\"" + boundary + "\"; ");
-        ct.append("type=\"application/xop+xml\"; ");
-        ct.append("start=\"<" + soapPartId + ">\"; ");
-        ct.append("start-info=" + message.getAttachmentMimeType());
-        return ct.toString();
-    }
 }

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/ByteDataSource.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/ByteDataSource.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java (from r481031, incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java&r1=481031&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/binding/attachment/CachedOutputStream.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java Thu Nov 30 11:19:29 2006
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.attachment;
+package org.apache.cxf.attachment;
 
 import java.io.IOException;
 import java.io.PipedInputStream;

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,98 @@
+/**
+ * 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.attachment;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+
+final class DelegatingInputStream extends InputStream {
+    private InputStream is;
+    private boolean isClosed;
+
+    /**
+     * @param source
+     */
+    DelegatingInputStream(InputStream is) {
+        this.is = is;
+    }
+
+    @Override
+    public void close() throws IOException {
+        is.close();
+        isClosed = true;
+    }
+
+    public boolean isClosed() {
+        return isClosed;
+    }
+
+    public void setClosed(boolean closed) {
+        this.isClosed = closed;
+    }
+
+    public int read() throws IOException {
+        return this.is.read();
+    }
+
+    @Override
+    public int available() throws IOException {
+        return this.is.available();
+    }
+
+    @Override
+    public synchronized void mark(int arg0) {
+        this.is.mark(arg0);
+    }
+
+    @Override
+    public boolean markSupported() {
+        return this.is.markSupported();
+    }
+
+    @Override
+    public int read(byte[] bytes, int arg1, int arg2) throws IOException {
+        return this.is.read(bytes, arg1, arg2);
+    }
+
+    @Override
+    public int read(byte[] bytes) throws IOException {
+        return this.is.read(bytes);
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        this.is.reset();
+    }
+
+    @Override
+    public long skip(long n) throws IOException {
+        return this.is.skip(n);
+    }
+
+    public void setInputStream(InputStream inputStream) {
+        this.is = inputStream;
+    }
+
+    
+    public InputStream getInputStream() {
+        return is;
+    }
+}
\ No newline at end of file

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/DelegatingInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,146 @@
+/**
+ * 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.attachment;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cxf.message.Attachment;
+
+public class LazyAttachmentCollection implements Collection<Attachment> {
+    private AttachmentDeserializer deserializer;
+    private final List<Attachment> attachments = new ArrayList<Attachment>();
+    
+    public LazyAttachmentCollection(AttachmentDeserializer deserializer) {
+        super();
+        this.deserializer = deserializer;
+    }
+
+    public List<Attachment> getLoadedAttachments() {
+        return attachments;
+    }
+
+    private void loadAll() {
+        try {
+            Attachment a = deserializer.readNext();
+            while (a != null) {
+                attachments.add(a);
+                a = deserializer.readNext();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public Iterator<Attachment> iterator() {
+        return new Iterator<Attachment>() {
+            int current;
+            
+            public boolean hasNext() {
+                if (attachments.size() > current) {
+                    return true;
+                }
+                
+                // check if there is another attachment
+                try {
+                    Attachment a = deserializer.readNext();
+                    if (a == null) {
+                        return false;
+                    } else {
+                        attachments.add(a);
+                        return true;
+                    }
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            public Attachment next() {
+                Attachment a = attachments.get(current);
+                current++;
+                return a;
+            }
+
+            public void remove() {
+                attachments.remove(current);
+            }
+            
+        };
+    }
+    
+    public int size() {
+        loadAll();
+        
+        return attachments.size();
+    }
+
+    public boolean add(Attachment arg0) {
+        return attachments.add(arg0);
+    }
+
+    public boolean addAll(Collection<? extends Attachment> arg0) {
+        return attachments.addAll(arg0);
+    }
+
+    public void clear() {
+        attachments.clear();   
+    }
+
+    public boolean contains(Object arg0) {
+        return attachments.contains(arg0);
+    }
+
+    public boolean containsAll(Collection<?> arg0) {
+        return attachments.containsAll(arg0);
+    }
+
+    public boolean isEmpty() {
+        return attachments.isEmpty();
+    }
+
+    public boolean remove(Object arg0) {
+        return attachments.remove(arg0);
+    }
+
+    public boolean removeAll(Collection<?> arg0) {
+        return attachments.removeAll(arg0);
+    }
+
+    public boolean retainAll(Collection<?> arg0) {
+        return attachments.retainAll(arg0);
+    }
+
+    public Object[] toArray() {
+        loadAll();
+        
+        return attachments.toArray();
+    }
+
+    public <T> T[] toArray(T[] arg0) {
+        loadAll();
+        
+        return attachments.toArray(arg0);
+    }
+
+
+
+}

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,89 @@
+/**
+ * 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.attachment;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+import javax.activation.DataSource;
+
+import org.apache.cxf.message.Attachment;
+
+/**
+ * A DataSource which will search through a Collection of attachments so as to 
+ * lazily load the attachment from the collection. This allows streaming attachments
+ * with databinding toolkits like JAXB.
+ */
+public class LazyDataSource implements DataSource {
+    private DataSource dataSource;
+    private Collection<Attachment> attachments;
+    private String id;
+    
+    public LazyDataSource(String id, Collection<Attachment> attachments) {
+        super();
+        this.id = id;
+        this.attachments = attachments;
+    }
+
+    private synchronized void load() {
+        if (dataSource == null) {
+            for (Attachment a : attachments) {
+                if (a.getId().equals(id)) {
+                    this.dataSource = a.getDataHandler().getDataSource();
+                    break;
+                }
+            }
+        }
+    }
+    
+    public String getContentType() {
+        load();
+        
+        return dataSource.getContentType();
+    }
+
+    public InputStream getInputStream() throws IOException {
+        load();
+        
+        return dataSource.getInputStream();
+    }
+
+    public String getName() {
+        load();
+        
+        return dataSource.getName();
+    }
+
+    public OutputStream getOutputStream() throws IOException {
+        load();
+        
+        return dataSource.getOutputStream();
+    }
+
+    public DataSource getDataSource() {
+        return dataSource;
+    }
+
+    public void setDataSource(DataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+}

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/LazyDataSource.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java?view=auto&rev=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java Thu Nov 30 11:19:29 2006
@@ -0,0 +1,105 @@
+/**
+ * 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.attachment;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+
+public class MimeBodyPartInputStream extends InputStream {
+
+    PushbackInputStream inStream;
+
+    boolean boundaryFound;
+
+    byte[] boundary;
+
+    public MimeBodyPartInputStream(PushbackInputStream inStreamParam, byte[] boundaryParam) {
+        super();
+        this.inStream = inStreamParam;
+        this.boundary = boundaryParam;
+    }
+
+    public int read() throws IOException {
+        boolean needUnread0d0a = false;
+        if (boundaryFound) {
+            return -1;
+        }
+
+        // read the next value from stream
+        int value = inStream.read();
+        // A problem occured because all the mime parts tends to have a /r/n
+        // at the end. Making it hard to transform them to correct
+        // DataSources.
+        // This logic introduced to handle it
+        if (value == 13) {
+            value = inStream.read();
+            if (value != 10) {
+                inStream.unread(value);
+                return 13;
+            } else {
+                value = inStream.read();
+                if ((byte) value != boundary[0]) {
+                    inStream.unread(value);
+                    inStream.unread(10);
+                    return 13;
+                } else {
+                    needUnread0d0a = true;
+                }
+            }
+        } else if ((byte) value != boundary[0]) {
+            return value;
+        }
+        // read value is the first byte of the boundary. Start matching the
+        // next characters to find a boundary
+        int boundaryIndex = 0;
+        while ((boundaryIndex < boundary.length) && ((byte) value == boundary[boundaryIndex])) {
+            value = inStream.read();
+            boundaryIndex++;
+        }
+        if (boundaryIndex == boundary.length) {
+            // boundary found
+            boundaryFound = true;
+            // read the end of line character
+            if (inStream.read() == 45 && value == 45) {
+                // Last mime boundary should have a succeeding "--"
+                // as we are on it, read the terminating CRLF
+                inStream.read();
+                inStream.read();
+            }
+            return -1;
+        }
+        // Boundary not found. Restoring bytes skipped.
+        // write first skipped byte, push back the rest
+        if (value != -1) {
+            // Stream might have ended
+            inStream.unread(value);
+        }
+        if (needUnread0d0a) {
+            inStream.unread(boundary, 0, boundaryIndex);
+            inStream.unread(10);
+            value = 13;
+        } else {
+            inStream.unread(boundary, 1, boundaryIndex - 1);                
+            value = boundary[0];
+        }
+        return value;
+    }
+}
\ No newline at end of file

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/MimeBodyPartInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java (from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java&r1=480652&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/AttachmentOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java Thu Nov 30 11:19:29 2006
@@ -17,24 +17,18 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.soap.interceptor;
+package org.apache.cxf.interceptor;
 
 import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collection;
 import java.util.ResourceBundle;
 
-import org.apache.cxf.binding.attachment.AttachmentSerializer;
-import org.apache.cxf.binding.soap.SoapFault;
-import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.attachment.AttachmentSerializer;
 import org.apache.cxf.common.i18n.BundleUtils;
-import org.apache.cxf.common.i18n.Message;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.io.AbstractCachedOutputStream;
-import org.apache.cxf.message.Attachment;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
 
-public class AttachmentOutInterceptor extends AbstractSoapInterceptor {
+public class AttachmentOutInterceptor extends AbstractPhaseInterceptor<Message> {
 
     private static final ResourceBundle BUNDLE = BundleUtils.getBundle(AttachmentOutInterceptor.class);
 
@@ -43,54 +37,22 @@
         setPhase(Phase.PRE_STREAM);
     }
 
-    public void handleMessage(SoapMessage message) throws Fault {
-
+    public void handleMessage(Message message) throws Fault {
         if (!Boolean.TRUE.equals(message.getContextualProperty(
                 org.apache.cxf.message.Message.MTOM_ENABLED))) {
             return;
         }
 
-        OutputStream os = message.getContent(OutputStream.class);
-        CachedStream cs = new CachedStream();
-        message.setContent(OutputStream.class, cs);
-
-        // Calling for soap out interceptor
-        if (!message.getInterceptorChain().doIntercept(message)
-                && message.getContent(Exception.class) != null) {
-            if (message.getContent(Exception.class) instanceof Fault) {
-                throw (Fault) message.getContent(Exception.class);
-            } else {
-                throw new Fault(message.getContent(Exception.class));
-            }
-        }
-        // Set back the output stream
-        message.setContent(OutputStream.class, os);
+        AttachmentSerializer serializer = new AttachmentSerializer(message);
         try {
-            Collection<Attachment> attachments = message.getAttachments();
-            cs.flush();
-            if (attachments.size() > 0) {
-                AttachmentSerializer as = new AttachmentSerializer(message, cs.getInputStream(), os);
-                as.serializeMultipartMessage();
-            } else {
-                // get wire connection, and copy xml infoset directly into it
-                os.flush();
-                AbstractCachedOutputStream.copyStream(cs.getInputStream(), os, 64 * 1024);
-            }
-        } catch (IOException ioe) {
-            throw new SoapFault(new Message("ATTACHMENT_IO", BUNDLE, ioe.toString()), 
-                    SoapFault.ATTACHMENT_IO);
+            serializer.writeProlog();
+            
+            message.getInterceptorChain().doIntercept(message);
+            
+            serializer.writeAttachments();
+        } catch (IOException e) {
+            throw new Fault(new org.apache.cxf.common.i18n.Message("WRITE_ATTACHMENTS", BUNDLE), e);
         }
     }
 
-    private class CachedStream extends AbstractCachedOutputStream {
-        protected void doFlush() throws IOException {
-            currentStream.flush();
-        }
-
-        protected void doClose() throws IOException {
-        }
-
-        protected void onWrite() throws IOException {
-        }
-    }
 }

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties Thu Nov 30 11:19:29 2006
@@ -29,3 +29,4 @@
 COULD_NOT_SEND=Could not send Message.
 NO_PART_FOUND=Message part {0} was not recognized.
 ORDERED_PARAM_REQUIRED=Parameter should be ordered in the following sequence: {0}
+WRITE_ATTACHMENTS=Could not write attachments.

Copied: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java (from r480652, incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java?view=diff&rev=481043&p1=incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java&r1=480652&p2=incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/MultipartMessageInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MultipartMessageInterceptor.java Thu Nov 30 11:19:29 2006
@@ -17,11 +17,12 @@
  * under the License.
  */
 
-package org.apache.cxf.binding.soap.interceptor;
+package org.apache.cxf.interceptor;
 
+import java.io.IOException;
 import java.util.logging.Logger;
 
-import org.apache.cxf.binding.attachment.AttachmentDeserializer;
+import org.apache.cxf.attachment.AttachmentDeserializer;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
@@ -49,9 +50,17 @@
             LOG.info("MultipartMessageInterceptor skipped in HTTP GET method");
             return;
         }
+        
+        if (!Boolean.TRUE.equals(
+            message.getContextualProperty(org.apache.cxf.message.Message.MTOM_ENABLED))) {
+            return;
+        }
+
         AttachmentDeserializer ad = new AttachmentDeserializer(message);
-        if (ad.preprocessMessage()) {
-            message.put(AttachmentDeserializer.class, ad);
+        try {
+            ad.initializeAttachments();
+        } catch (IOException e) {
+            throw new Fault(e);
         }
     }
 

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainSetupInterceptor.java Thu Nov 30 11:19:29 2006
@@ -19,17 +19,12 @@
 
 package org.apache.cxf.interceptor;
 
-import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.cxf.Bus;
-import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.endpoint.Endpoint;
-import org.apache.cxf.helpers.HttpHeaderHelper;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
@@ -61,36 +56,13 @@
             outMessage = ep.getBinding().createMessage();
             ex.setOutMessage(outMessage);
         }
-        setUpContentType(outMessage);
 
         Message faultMessage = message.getExchange().getOutFaultMessage();
         if (faultMessage == null) {
             faultMessage = ep.getBinding().createMessage();            
             ex.setOutFaultMessage(faultMessage);
         }
-
-        setUpContentType(faultMessage);
-        
         outMessage.setInterceptorChain(getOutInterceptorChain(ex));
-    }
-    
-    @SuppressWarnings("unchecked")
-    private void setUpContentType(Message message) {
-        if (StringUtils.isEmpty((String)message.get(Message.CONTENT_TYPE))) {
-            return;
-        }
-        
-        Map<String, List<String>> headers = (Map<String, List<String>>)message.get(Message.PROTOCOL_HEADERS);
-        if (headers == null) {
-            headers = new HashMap<String, List<String>>();
-            message.put(Message.PROTOCOL_HEADERS, headers);         
-        }
-        
-        LOG.info("OutgoingChainSetupInterceptor set the content-type to: " 
-                 + message.get(Message.CONTENT_TYPE));
-
-        headers.put(HttpHeaderHelper.CONTENT_TYPE,  
-                    Arrays.asList(new String[] {(String)message.get(Message.CONTENT_TYPE)}));
     }
     
     public static InterceptorChain getOutInterceptorChain(Exchange ex) {

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java?view=diff&rev=481043&r1=481042&r2=481043
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedInInterceptor.java Thu Nov 30 11:19:29 2006
@@ -113,7 +113,6 @@
                 MessagePartInfo part = itr.next();
                 objects.add(dr.read(part, message));
             }
-
         }
 
         message.setContent(List.class, objects);



Re: svn commit: r481043 [1/2] - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/message/ rt/bindings/http/src/test/java/org/apache/cxf/binding/http/ rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/ rt/bindings/soap/src/main/java/org/ap...

Posted by Andrea Smyth <an...@iona.com>.
dandiep@apache.org wrote:

>Author: dandiep
>Date: Thu Nov 30 11:19:29 2006
>New Revision: 481043
>
>URL: http://svn.apache.org/viewvc?view=rev&rev=481043
>Log:
>o Rewrite MTOM support to be completely streamed based. If attachments
>  are accessed out of order, they are cached. This is done through a 
>  LazyAttachmentCollection. The iterator will iterate over attachments
>  as they are accessed, loading them one at a time until the correct
>  one is found. On the outgoing side the AttachmentSerializer allows
>  us to write out the attachments in steps.
>o Move MTOM interceptors into core as they are dependent on SOAP and
>  some people would like to use it with XML over HTTP.
>o Unify handling of Message.CONTENT_TYPE, transports are now expected
>  to deal with it correctly and we shouldn't have to muck with the protocol
>  headers to set the content type (like we were doing in 
>  OutgoingChainSetupInterceptor).
>o Rename some message properties to make it easier for configuration.
>o Rewrite server side mtom test to not use the client to make it easy
>  to test and debug.
>o Remove ugly Message.getAttachmentMimeType() method
>o Try to use IOUtils.copy() in more places to reduce duplication
>o This has not been interop tested. I think there may be an issue or two
>  when using with .NET 2.0, but I need to test and track down the issue
>  (will do so soon).
>
>  
>
I am seeing the ClientMtomXopTest failing now on Windows:
[surefire] Running org.apache.cxf.systest.mtom.ClientMtomXopTest
[surefire] Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 7.13 sec
[surefire]
[surefire] testMtomXop(org.apache.cxf.systest.mtom.ClientMtomXopTest)  
Time elap
sed: 1.463 sec  <<< FAILURE!
junit.framework.ComparisonFailure: attachinfo changed expected:<...
 > but was:<...>
        at junit.framework.Assert.assertEquals(Assert.java:81)
        at 
org.apache.cxf.systest.mtom.ClientMtomXopTest.testMtomXop(ClientMtomXopTest.java:155)
....

Any ideas?
Andrea.