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 2007/06/13 00:49:12 UTC

svn commit: r546656 [1/2] - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/io/ api/src/main/java/org/apache/cxf/message/ api/src/main/java/org/apache/cxf/phase/ common/common/src/main/java/org/apache/cxf/helpers/ rt/bindings/http/src/main/ja...

Author: dandiep
Date: Tue Jun 12 15:49:08 2007
New Revision: 546656

URL: http://svn.apache.org/viewvc?view=rev&rev=546656
Log:

Refactoring of the low level IO layer inside CXF.

Remove the dependence on flush() being called ONCE and only once
inside CXF. There was the assumption in all the code that things would 
be cached until we actually finished databinding, which is a bad assumption. 
There are a couple problems with this: 
1. The Soap envelope writer was writing the envelope twice if a fault was 
thrown during databinding and the stream was already flushed. (i.e. during
validation)
2. The code didn't differentiate between the type of caching that was going
on. i.e. are we a) writing to the underlying stream AND caching the message
at the same time. Or b) are we caching the message and then writing on close()

Ensure that the RM and Logging layers correctly do their work on close() 
instead of flush(). 

Transports now pass in the underlying stream. The RM layer and logging
interceptors correct detect when a cached stream is not being used
and act accordingly. This is much more robust as I/O transformations
are a very valid use case an many people will want to switch the 
underlying streams. We also shouldn't force transport writers to 
use CachedOutputStream. 

Rename AbstractCachedOutputStream to CachedOutputStream and make
it a non-abstract class. This cuts down on the number of CachedOutputStream
classes laying around! There are now two extended implementations of
COS as well:
1. WriteOnCloseOutputStream. This caches the message until the outputstream
is closed. This is needed for the RM scenarios where we are caching the message
until the CreateSequence is done. We don't want to open the connection until
all of this is done. (I think we could probably reset this output stream 
as soon as the createsequence is finished though)
2. CacheAndWriteOutputStream. This caches the message while it is written
to the underlying stream at the same time. Useful for logging.

Update the DataBinding code to have JAXB write directly to the OutputStream
whenever possible. This gives a great performance improvement for some scenarios.

Refactor the JAXB code so we don't have so many data readers/writers.

TODO: Make RM and Logging work when the message is larger than memory or the 
CachedOutputStream writes to disk.

TODO: Fix HTTPS 401 Redirect test 


Added:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java
      - copied, changed from r546239, incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractCachedOutputStream.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/CacheAndWriteOutputStream.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/WriteOnCloseOutputStream.java   (with props)
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java   (with props)
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java   (with props)
Removed:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractCachedOutputStream.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/CachedOutputStream.java
    incubator/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/CachedOutputStream.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/EventDataReader.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/EventDataWriter.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/NodeDataReader.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/NodeDataWriter.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/XMLStreamDataReader.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/XMLStreamDataWriter.java
    incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/CachedOutputStream.java
Modified:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractWrappedOutputStream.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStreamCallback.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageUtils.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
    incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/DatabindingOutSetupInterceptor.java
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/URIParameterOutInterceptor.java
    incubator/cxf/trunk/rt/bindings/jbi/src/main/java/org/apache/cxf/binding/jbi/interceptor/JBIWrapperOutInterceptor.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/RPCOutInterceptor.java
    incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapOutInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/NodeDataReader.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataReader.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AbstractOutDatabindingInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/BareOutInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingInInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingOutInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutFaultChainInitiatorObserver.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/StaxOutInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AbstractServiceFactoryBean.java
    incubator/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/CachedOutputStreamTest.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/test/java/org/apache/cxf/jaxb/JAXBDataBindingTest.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerFaultOutInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptorTest.java
    incubator/cxf/trunk/rt/transports/http-jetty/src/test/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestinationTest.java
    incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java
    incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
    incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java
    incubator/cxf/trunk/rt/transports/jbi/src/main/java/org/apache/cxf/transport/jbi/JBIConduitOutputStream.java
    incubator/cxf/trunk/rt/transports/jbi/src/main/java/org/apache/cxf/transport/jbi/JBIDestinationOutputStream.java
    incubator/cxf/trunk/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
    incubator/cxf/trunk/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
    incubator/cxf/trunk/rt/transports/local/src/main/java/org/apache/cxf/transport/local/LocalConduit.java
    incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/Messages.properties
    incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RMUtils.java
    incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RetransmissionCallback.java
    incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RetransmissionInterceptor.java
    incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/soap/RetransmissionQueueImpl.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/dispatch/DispatchClientServerTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/http/HTTPConduitTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/schema_validation/ValidationClientServerTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ControlImpl.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/MessageLossSimulator.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ServerPersistenceTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/util/OutMessageRecorder.java

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractWrappedOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractWrappedOutputStream.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractWrappedOutputStream.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractWrappedOutputStream.java Tue Jun 12 15:49:08 2007
@@ -19,25 +19,51 @@
 
 package org.apache.cxf.io;
 
-import org.apache.cxf.message.Message;
+import java.io.IOException;
+import java.io.OutputStream;
 
-public abstract class AbstractWrappedOutputStream extends AbstractCachedOutputStream {
+/**
+ * Provides a convenient hook onFirstWrite() for those needing
+ * to wrap an output stream.
+ *
+ */
+public abstract class AbstractWrappedOutputStream extends OutputStream {
 
-    protected Message outMessage;
-    private boolean flushed;
+    protected OutputStream wrappedStream;
+    protected boolean written;
     
-    protected AbstractWrappedOutputStream(Message m) {
+    protected AbstractWrappedOutputStream() {
         super();
-        outMessage = m;
     }
 
-    /**
-     * @return true if already flushed
-     */
-    protected boolean alreadyFlushed() {
-        boolean ret = flushed;
-        flushed = true;
-        return ret;
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        if (!written) {
+            onFirstWrite();
+            written = true;
+        }
+        wrappedStream.write(b, off, len);
+    }
+
+    protected void onFirstWrite() throws IOException {
+    }
+
+    @Override
+    public void write(byte[] b) throws IOException {
+        if (!written) {
+            onFirstWrite();
+            written = true;
+        }
+        wrappedStream.write(b);
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        if (!written) {
+            onFirstWrite();
+            written = true;
+        }
+        wrappedStream.write(b);
     }
 
 }

Copied: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java (from r546239, incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractCachedOutputStream.java)
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java?view=diff&rev=546656&p1=incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractCachedOutputStream.java&r1=546239&p2=incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java&r2=546656
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/AbstractCachedOutputStream.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStream.java Tue Jun 12 15:49:08 2007
@@ -38,7 +38,7 @@
 
 import org.apache.cxf.common.util.Base64Utility;
 
-public abstract class AbstractCachedOutputStream extends OutputStream {
+public class CachedOutputStream extends OutputStream {
 
     protected OutputStream currentStream;
 
@@ -54,12 +54,12 @@
 
     private List<CachedOutputStreamCallback> callbacks;
 
-    public AbstractCachedOutputStream(PipedInputStream stream) throws IOException {
+    public CachedOutputStream(PipedInputStream stream) throws IOException {
         currentStream = new PipedOutputStream(stream);
         inmem = true;
     }
 
-    public AbstractCachedOutputStream() {
+    public CachedOutputStream() {
         currentStream = new ByteArrayOutputStream();
         inmem = true;
     }
@@ -85,7 +85,9 @@
      * Perform any actions required on stream flush (freeze headers, reset
      * output stream ... etc.)
      */
-    protected abstract void doFlush() throws IOException;
+    protected void doFlush() throws IOException {
+        
+    }
 
     public void flush() throws IOException {
         currentStream.flush();
@@ -100,17 +102,20 @@
     /**
      * Perform any actions required on stream closure (handle response etc.)
      */
-    protected abstract void doClose() throws IOException;
+    protected void doClose() throws IOException {
+        
+    }
 
     public void close() throws IOException {
         currentStream.flush();
-        currentStream.close();
-        dispose();
         if (null != callbacks) {
             for (CachedOutputStreamCallback cb : callbacks) {
                 cb.onClose(this);
             }
         }
+        
+        currentStream.close();
+        dispose();
         doClose();
     }
 
@@ -130,8 +135,8 @@
      * @throws IOException
      */
     public void resetOut(OutputStream out, boolean copyOldContent) throws IOException {
-        if (currentStream instanceof AbstractCachedOutputStream) {
-            AbstractCachedOutputStream ac = (AbstractCachedOutputStream) currentStream;
+        if (currentStream instanceof CachedOutputStream) {
+            CachedOutputStream ac = (CachedOutputStream) currentStream;
             InputStream in = ac.getInputStream();
             copyStream(in, out, (int) threshold);
         } else {
@@ -206,7 +211,9 @@
             .append("]").toString();
     }
 
-    protected abstract void onWrite() throws IOException;
+    protected void onWrite() throws IOException {
+        
+    }
 
     public void write(byte[] b, int off, int len) throws IOException {
         onWrite();
@@ -285,5 +292,4 @@
     public void setThreshold(long threshold) {
         this.threshold = threshold;
     }
-
 }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStreamCallback.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStreamCallback.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStreamCallback.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/io/CachedOutputStreamCallback.java Tue Jun 12 15:49:08 2007
@@ -21,7 +21,7 @@
 
 public interface CachedOutputStreamCallback {
 
-    void onClose(AbstractCachedOutputStream os);
-    void onFlush(AbstractCachedOutputStream os);
+    void onClose(CachedOutputStream os);
+    void onFlush(CachedOutputStream os);
 
 }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageUtils.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageUtils.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageUtils.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/MessageUtils.java Tue Jun 12 15:49:08 2007
@@ -19,6 +19,8 @@
 
 package org.apache.cxf.message;
 
+import org.w3c.dom.Node;
+
 
 /**
  * Holder for utility methods relating to messages.
@@ -108,6 +110,18 @@
             return true;
         }
         
+        return false;
+    }
+    
+    /**
+     * Returns true if the underlying content format is a W3C DOM or a SAAJ message.
+     */
+    public static boolean isDOMPresent(Message m) {
+        for (Class c : m.getContentFormats()) {
+            if (c.equals(Node.class) || c.getName().equals("javax.xml.soap.SOAPMessage")) {
+                return true;
+            }   
+        }
         return false;
     }
 

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java Tue Jun 12 15:49:08 2007
@@ -200,8 +200,8 @@
             try {
                 Interceptor currentInterceptor = iterator.next();
                
-                if (LOG.isLoggable(Level.FINE)) {
-                    LOG.fine("Invoking handleMessage on interceptor " + currentInterceptor);
+                if (LOG.isLoggable(Level.INFO)) {
+                    LOG.info("Invoking handleMessage on interceptor " + currentInterceptor);
                 }
                 currentInterceptor.handleMessage(message);
                 

Modified: incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java (original)
+++ incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/helpers/DOMUtils.java Tue Jun 12 15:49:08 2007
@@ -210,6 +210,19 @@
         }
         return null;
     }
+    /**
+     * Get the first direct child with a given type
+     */
+    public static Element getFirstElement(Node parent) {
+        Node n = parent.getFirstChild();
+        while (n != null && Node.ELEMENT_NODE != n.getNodeType()) {
+            n = n.getNextSibling();
+        }
+        if (n == null) {
+            return null;
+        }
+        return (Element) n;
+    }
 
     /**
      * Get the first direct child with a given type

Modified: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/DatabindingOutSetupInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/DatabindingOutSetupInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/DatabindingOutSetupInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/DatabindingOutSetupInterceptor.java Tue Jun 12 15:49:08 2007
@@ -21,6 +21,7 @@
 import javax.xml.stream.XMLStreamWriter;
 
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
 
 import org.apache.cxf.binding.http.HttpConstants;
 import org.apache.cxf.binding.http.URIMapper;
@@ -53,7 +54,7 @@
         
         if (client) {
             Document document = DOMUtils.createDocument();
-            message.setContent(Document.class, document);
+            message.setContent(Node.class, document);
             
             XMLStreamWriter writer = new W3CDOMStreamWriter(document);
             message.setContent(XMLStreamWriter.class, writer);

Modified: incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/URIParameterOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/URIParameterOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/URIParameterOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/URIParameterOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -65,7 +65,7 @@
             uri.append(location);
         }
 
-        Document d = message.getContent(Document.class);
+        Document d = (Document) message.getContent(Node.class);
         String encodedUri = encodeIri(uri.toString(), d);
 
         message.put(Message.ENDPOINT_ADDRESS, encodedUri);

Modified: incubator/cxf/trunk/rt/bindings/jbi/src/main/java/org/apache/cxf/binding/jbi/interceptor/JBIWrapperOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/jbi/src/main/java/org/apache/cxf/binding/jbi/interceptor/JBIWrapperOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/bindings/jbi/src/main/java/org/apache/cxf/binding/jbi/interceptor/JBIWrapperOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/jbi/src/main/java/org/apache/cxf/binding/jbi/interceptor/JBIWrapperOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -32,6 +32,7 @@
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.Phase;
+import org.apache.cxf.service.Service;
 import org.apache.cxf.service.model.BindingOperationInfo;
 import org.apache.cxf.service.model.MessagePartInfo;
 
@@ -48,7 +49,9 @@
     public void handleMessage(Message message) throws Fault {
         BindingOperationInfo bop = message.getExchange().get(BindingOperationInfo.class);
         XMLStreamWriter xmlWriter = getXMLStreamWriter(message);
-        DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, XMLStreamWriter.class);
+        Service service = message.getExchange().get(Service.class);
+        
+        DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, service, XMLStreamWriter.class);
 
         try {
             xmlWriter.setPrefix("jbi", JBIConstants.NS_JBI_WRAPPER);

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/RPCOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/RPCOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/RPCOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/RPCOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -24,7 +24,6 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 
-import org.apache.cxf.databinding.DataWriter;
 import org.apache.cxf.helpers.NSStack;
 import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
 import org.apache.cxf.interceptor.Fault;
@@ -52,7 +51,6 @@
             assert operation.getName() != null;
 
             XMLStreamWriter xmlWriter = getXMLStreamWriter(message);
-            DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, XMLStreamWriter.class);
 
             addOperationNode(nsStack, message, xmlWriter);
 
@@ -69,12 +67,7 @@
                 return;
             }
             
-            for (MessagePartInfo part : parts) {
-                int idx = part.getMessageInfo().getMessagePartIndex(part);
-                
-                Object o = objs.get(idx);
-                dataWriter.write(o, part, xmlWriter);
-            }
+            writeParts(message, message.getExchange(), operation, objs, parts);
             
             // Finishing the writing.
             xmlWriter.writeEndElement();            

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -20,6 +20,7 @@
 package org.apache.cxf.binding.soap.interceptor;
 
 
+import java.io.OutputStream;
 import java.util.List;
 import java.util.ResourceBundle;
 
@@ -41,8 +42,10 @@
 import org.apache.cxf.headers.HeaderProcessor;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.io.WriteOnCloseOutputStream;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.service.Service;
 import org.apache.cxf.service.model.BindingMessageInfo;
@@ -51,9 +54,11 @@
 import org.apache.cxf.service.model.ServiceModelUtil;
 import org.apache.cxf.staxutils.StaxUtils;
 
-
 public class SoapOutInterceptor extends AbstractSoapInterceptor {
+    public static final String WROTE_ENVELOPE_START = "wrote.envelope.start";
+    
     private static final ResourceBundle BUNDLE = BundleUtils.getBundle(SoapOutInterceptor.class);
+    
     private Bus bus;
     
     public SoapOutInterceptor(Bus b) {
@@ -66,6 +71,23 @@
     }
     
     public void handleMessage(SoapMessage message) {
+        // Yes this is ugly, but it avoids us from having to implement any kind of caching strategy
+        if (!MessageUtils.isTrue(message.get(WROTE_ENVELOPE_START))) {
+            writeSoapEnvelopeStart(message);
+            
+            OutputStream os = message.getContent(OutputStream.class);
+            // Unless we're caching the whole message in memory skip the envelope writing
+            // if there's a fault later.
+            if (!(os instanceof WriteOnCloseOutputStream) && !MessageUtils.isDOMPresent(message)) {
+                message.put(WROTE_ENVELOPE_START, Boolean.TRUE);
+            }
+        }
+
+        // Add a final interceptor to write end elements
+        message.getInterceptorChain().add(new SoapOutEndingInterceptor());
+    }
+    
+    private void writeSoapEnvelopeStart(SoapMessage message) {
         SoapVersion soapVersion = message.getVersion();
         try {            
             XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class);
@@ -113,9 +135,6 @@
             throw new SoapFault(
                 new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), e, soapVersion.getSender());
         }
-
-        // Add a final interceptor to write end elements
-        message.getInterceptorChain().add(new SoapOutEndingInterceptor());
     }
     
     private boolean handleHeaderPart(boolean preexistingHeaders, SoapMessage message) {

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/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=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java Tue Jun 12 15:49:08 2007
@@ -38,6 +38,7 @@
 import javax.mail.internet.InternetHeaders;
 
 import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.message.Message;
 

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/NodeDataReader.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/NodeDataReader.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/NodeDataReader.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/NodeDataReader.java Tue Jun 12 15:49:08 2007
@@ -33,12 +33,12 @@
 
 import org.xml.sax.InputSource;
 
-import org.apache.cxf.attachment.CachedOutputStream;
 import org.apache.cxf.common.i18n.Message;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.databinding.DataReader;
 import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.service.model.MessagePartInfo;
 

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataReader.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataReader.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataReader.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataReader.java Tue Jun 12 15:49:08 2007
@@ -32,17 +32,18 @@
 import javax.xml.validation.Schema;
 
 import org.w3c.dom.Document;
-
 import org.xml.sax.InputSource;
 
-import org.apache.cxf.attachment.CachedOutputStream;
 import org.apache.cxf.common.i18n.Message;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.databinding.DataReader;
 import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.message.Attachment;
 import org.apache.cxf.service.model.MessagePartInfo;
 import org.apache.cxf.staxutils.StaxUtils;
+
+
 
 public class XMLStreamDataReader implements DataReader<XMLStreamReader> {
     private static final Logger LOG = LogUtils.getL7dLogger(XMLStreamDataReader.class);

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AbstractOutDatabindingInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AbstractOutDatabindingInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AbstractOutDatabindingInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AbstractOutDatabindingInterceptor.java Tue Jun 12 15:49:08 2007
@@ -19,23 +19,31 @@
 
 package org.apache.cxf.interceptor;
 
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
+import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.validation.Schema;
 
 import org.apache.cxf.databinding.DataWriter;
 import org.apache.cxf.message.Attachment;
+import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.service.Service;
-import org.apache.cxf.service.model.ServiceModelUtil;
+import org.apache.cxf.service.model.BindingInfo;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.apache.cxf.service.model.MessagePartInfo;
 import org.apache.cxf.wsdl.EndpointReferenceUtils;
 
 public abstract class AbstractOutDatabindingInterceptor extends AbstractPhaseInterceptor<Message> {
 
+    public static final String DISABLE_OUTPUTSTREAM_OPTIMIZATION = "disable.outputstream.optimization";
+    
     /**
      * @deprecated
      */
@@ -54,8 +62,60 @@
         return Boolean.TRUE.equals(message.containsKey(Message.REQUESTOR_ROLE));
     }
     
-    protected <T> DataWriter<T> getDataWriter(Message message, Class<T> output) {
-        Service service = ServiceModelUtil.getService(message.getExchange());
+    protected void writeParts(Message message, Exchange exchange, 
+                              BindingOperationInfo operation, List<?> objs, 
+                              List<MessagePartInfo> parts) {
+        OutputStream out = message.getContent(OutputStream.class);
+        XMLStreamWriter xmlWriter = message.getContent(XMLStreamWriter.class);
+        Service service = exchange.get(Service.class);
+        if (out != null 
+            && writeToOutputStream(message, operation.getBinding(), service)
+            && !MessageUtils.isTrue(message.getContextualProperty(DISABLE_OUTPUTSTREAM_OPTIMIZATION))) {
+            if (xmlWriter != null) {
+                try {
+                    xmlWriter.writeCharacters("");
+                    xmlWriter.flush();
+                } catch (XMLStreamException e) {
+                    throw new Fault(e);
+                }
+            }
+            
+            DataWriter<OutputStream> osWriter = getDataWriter(message, service, OutputStream.class);
+            
+            for (MessagePartInfo part : parts) {
+                int idx = part.getMessageInfo().getMessagePartIndex(part);
+                
+                Object o = objs.get(idx);
+                osWriter.write(o, part, out);
+            }
+        } else {
+            DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, service, XMLStreamWriter.class);
+            
+            for (MessagePartInfo part : parts) {
+                int idx = part.getMessageInfo().getMessagePartIndex(part);
+                
+                Object o = objs.get(idx);
+                dataWriter.write(o, part, xmlWriter);
+            }
+        }
+    }
+    
+    protected boolean writeToOutputStream(Message m, BindingInfo info, Service s) {
+        /**
+         * Yes, all this code is EXTREMELY ugly. But it gives about a 60-70% performance
+         * boost with the JAXB RI, so its worth it. 
+         */
+        
+        if (s == null) {
+            return false;
+        }
+        
+        return info.getClass().getName().equals("org.apache.cxf.binding.soap.model.SoapBindingInfo") 
+            && s.getDataBinding().getClass().getName().equals("org.apache.cxf.jaxb.JAXBDataBinding")
+            && !MessageUtils.isDOMPresent(m);
+    }
+    
+    protected <T> DataWriter<T> getDataWriter(Message message, Service service, Class<T> output) {
         DataWriter<T> writer = service.getDataBinding().createWriter(output);
         
         Collection<Attachment> atts = message.getAttachments();

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/BareOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/BareOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/BareOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/BareOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -20,9 +20,6 @@
 package org.apache.cxf.interceptor;
 import java.util.List;
 
-import javax.xml.stream.XMLStreamWriter;
-
-import org.apache.cxf.databinding.DataWriter;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.Phase;
@@ -44,9 +41,11 @@
         if (operation == null) {
             return;
         }
-        
-        DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, XMLStreamWriter.class);
-        XMLStreamWriter xmlWriter = message.getContent(XMLStreamWriter.class);
+
+        List<?> objs = message.getContent(List.class);
+        if (objs == null || objs.size() == 0) {
+            return;
+        }
         
         List<MessagePartInfo> parts = null;
         BindingMessageInfo bmsg = null;
@@ -65,17 +64,7 @@
             parts = bmsg.getMessageParts();
         }
         
-        List<?> objs = message.getContent(List.class);
-        if (objs == null) {
-            return;
-        }
-        
-        for (MessagePartInfo part : parts) {
-            int idx = part.getMessageInfo().getMessagePartIndex(part);
-            
-            Object o = objs.get(idx);
-            dataWriter.write(o, part, xmlWriter);
-        }
+        writeParts(message, exchange, operation, objs, parts);
     }
-    
+
 }

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingInInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingInInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingInInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingInInterceptor.java Tue Jun 12 15:49:08 2007
@@ -57,8 +57,11 @@
             is.close();
             bos.close();
 
-            LOG.info("Inbound message: " + bos.toString());
-
+            LOG.info("Inbound Message\n" 
+                     + "--------------------------------------\n"
+                     + bos.toString()
+                     + "\n--------------------------------------");
+            
             message.setContent(InputStream.class, new ByteArrayInputStream(bos.toByteArray()));
 
         } catch (IOException e) {

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/LoggingOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -25,7 +25,8 @@
 import java.util.logging.Logger;
 
 import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import org.apache.cxf.io.CacheAndWriteOutputStream;
+import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.io.CachedOutputStreamCallback;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
@@ -39,41 +40,38 @@
     private static final Logger LOG = LogUtils.getL7dLogger(LoggingOutInterceptor.class); 
 
     public LoggingOutInterceptor() {
-        super(Phase.PRE_PROTOCOL);
+        super(Phase.PRE_STREAM);
         addBefore(StaxOutInterceptor.class.getName());
     }
     
     public void handleMessage(Message message) throws Fault {
-        OutputStream os = message.getContent(OutputStream.class);
+        final OutputStream os = message.getContent(OutputStream.class);
         if (os == null) {
             return;
         }
-        if (os instanceof AbstractCachedOutputStream) {
-            ((AbstractCachedOutputStream)os).registerCallback(new LoggingCallback());
-        }
+        
+        // Write the output while caching it for the log message
+        final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os);
+        message.setContent(OutputStream.class, newOut);
+        newOut.registerCallback(new LoggingCallback());
     }
 
     class LoggingCallback implements CachedOutputStreamCallback {
 
-        private boolean flushed;
-
-        public void onFlush(AbstractCachedOutputStream cos) {  
-            if (!flushed) {
-                OutputStream os = cos.getOut();
-                if (os instanceof ByteArrayOutputStream) {
-                    ByteArrayOutputStream bos = (ByteArrayOutputStream)os;
-                    if (LOG.isLoggable(Level.INFO)) {
-                        LOG.info("Outbound message: " + bos.toString());
-                    }
-                }
-                flushed = true;
-                // any further changes will not be logged
-            }
+        public void onFlush(CachedOutputStream cos) {  
+            
         }
         
-        public void onClose(AbstractCachedOutputStream cos) {
+        public void onClose(CachedOutputStream cos) {
+            OutputStream os = cos.getOut();
+            if (os instanceof ByteArrayOutputStream && LOG.isLoggable(Level.INFO)) {
+                // TODO - make this work with large messages
+                LOG.info("Outbound Message \n"
+                         + "--------------------------------------\n"
+                         + os.toString()
+                         + "\n--------------------------------------");
+            }
         }
         
     } 
-    
 }

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutFaultChainInitiatorObserver.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutFaultChainInitiatorObserver.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutFaultChainInitiatorObserver.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutFaultChainInitiatorObserver.java Tue Jun 12 15:49:08 2007
@@ -49,4 +49,4 @@
     protected boolean isOutboundObserver() {
         return true;
     }
-}
+}
\ No newline at end of file

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/StaxOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/StaxOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/StaxOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/StaxOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -52,8 +52,9 @@
 
     public void handleMessage(Message message) {
         OutputStream os = message.getContent(OutputStream.class);
+        XMLStreamWriter writer = message.getContent(XMLStreamWriter.class);
 
-        if (os == null) {
+        if (os == null || writer != null) {
             return;
         }
         // assert os != null;
@@ -70,7 +71,6 @@
             message.put(Message.ENCODING, encoding);
         }
         
-        XMLStreamWriter writer;
         try {
             writer = getXMLOutputFactory(message).createXMLStreamWriter(os, encoding);
         } catch (XMLStreamException e) {

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/CacheAndWriteOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/CacheAndWriteOutputStream.java?view=auto&rev=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/CacheAndWriteOutputStream.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/CacheAndWriteOutputStream.java Tue Jun 12 15:49:08 2007
@@ -0,0 +1,68 @@
+/**
+ * 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.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This outputstream implementation will both write to the outputstream
+ * that is specified and cache the data at the same time. This allows us
+ * to go back and retransmit the data at a later time if necessary.
+ *
+ */
+public class CacheAndWriteOutputStream extends CachedOutputStream {
+
+    OutputStream flowThroughStream;
+    
+    public CacheAndWriteOutputStream(OutputStream stream) {
+        super();
+        flowThroughStream = stream;
+    }
+
+    @Override
+    protected void doClose() throws IOException {
+        flowThroughStream.flush();
+        flowThroughStream.close();
+    }
+
+    @Override
+    protected void onWrite() throws IOException {
+        // does nothing
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        flowThroughStream.write(b);
+        super.write(b);
+    }
+    
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        flowThroughStream.write(b, off, len);
+        super.write(b, off, len);
+    }
+    
+    @Override
+    public void write(byte[] b) throws IOException {
+        flowThroughStream.write(b);
+        super.write(b);
+    }
+}

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/WriteOnCloseOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/WriteOnCloseOutputStream.java?view=auto&rev=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/WriteOnCloseOutputStream.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/io/WriteOnCloseOutputStream.java Tue Jun 12 15:49:08 2007
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This outputstream implementation will cache the message until close()
+ * is called, at which point it will write the message to the OutputStream
+ * supplied via the constructor.
+ */
+public class WriteOnCloseOutputStream extends CachedOutputStream {
+
+    OutputStream flowThroughStream;
+    
+    public WriteOnCloseOutputStream(OutputStream stream) {
+        super();
+        flowThroughStream = stream;
+    }
+
+    @Override
+    protected void doClose() throws IOException {
+        resetOut(flowThroughStream, true);
+        flowThroughStream.flush();
+        flowThroughStream.close();
+    }
+}

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

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

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

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AbstractServiceFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AbstractServiceFactoryBean.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AbstractServiceFactoryBean.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/service/factory/AbstractServiceFactoryBean.java Tue Jun 12 15:49:08 2007
@@ -21,6 +21,8 @@
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.databinding.DataBinding;
+import org.apache.cxf.interceptor.LoggingInInterceptor;
+import org.apache.cxf.interceptor.LoggingOutInterceptor;
 import org.apache.cxf.interceptor.OutgoingChainInterceptor;
 import org.apache.cxf.interceptor.ServiceInvokerInterceptor;
 import org.apache.cxf.service.Service;
@@ -35,6 +37,9 @@
     protected void initializeDefaultInterceptors() {
         service.getInInterceptors().add(new ServiceInvokerInterceptor());
         service.getInInterceptors().add(new OutgoingChainInterceptor());
+        service.getInInterceptors().add(new LoggingInInterceptor());
+        service.getOutInterceptors().add(new LoggingOutInterceptor());
+        service.getOutFaultInterceptors().add(new LoggingOutInterceptor());
     }
     
     protected void initializeDataBindings() {

Modified: incubator/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/CachedOutputStreamTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/CachedOutputStreamTest.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/CachedOutputStreamTest.java (original)
+++ incubator/cxf/trunk/rt/core/src/test/java/org/apache/cxf/transport/CachedOutputStreamTest.java Tue Jun 12 15:49:08 2007
@@ -21,6 +21,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
+import org.apache.cxf.io.CachedOutputStream;
 import org.junit.Assert;
 import org.junit.Test;
 

Modified: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBDataBinding.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBDataBinding.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBDataBinding.java (original)
+++ incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBDataBinding.java Tue Jun 12 15:49:08 2007
@@ -20,6 +20,7 @@
 package org.apache.cxf.jaxb;
 
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -63,12 +64,8 @@
 import org.apache.cxf.databinding.DataWriter;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.helpers.DOMUtils;
-import org.apache.cxf.jaxb.io.EventDataReader;
-import org.apache.cxf.jaxb.io.EventDataWriter;
-import org.apache.cxf.jaxb.io.NodeDataReader;
-import org.apache.cxf.jaxb.io.NodeDataWriter;
-import org.apache.cxf.jaxb.io.XMLStreamDataReader;
-import org.apache.cxf.jaxb.io.XMLStreamDataWriter;
+import org.apache.cxf.jaxb.io.DataReaderImpl;
+import org.apache.cxf.jaxb.io.DataWriterImpl;
 import org.apache.cxf.resource.URIResolver;
 import org.apache.cxf.service.Service;
 import org.apache.cxf.service.factory.ServiceConstructionException;
@@ -91,7 +88,8 @@
     private static final Class<?> SUPPORTED_READER_FORMATS[] = new Class<?>[] {Node.class,
                                                                                XMLEventReader.class,
                                                                                XMLStreamReader.class};
-    private static final Class<?> SUPPORTED_WRITER_FORMATS[] = new Class<?>[] {Node.class,
+    private static final Class<?> SUPPORTED_WRITER_FORMATS[] = new Class<?>[] {OutputStream.class,
+                                                                               Node.class,
                                                                                XMLEventWriter.class,
                                                                                XMLStreamWriter.class};
 
@@ -126,11 +124,13 @@
     @SuppressWarnings("unchecked")
     public <T> DataWriter<T> createWriter(Class<T> c) {
         if (c == XMLStreamWriter.class) {
-            return (DataWriter<T>)new XMLStreamDataWriter(context);
+            return (DataWriter<T>)new DataWriterImpl<XMLStreamWriter>(context);
+        } else if (c == OutputStream.class) {
+            return (DataWriter<T>)new DataWriterImpl<OutputStream>(context);            
         } else if (c == XMLEventWriter.class) {
-            return (DataWriter<T>)new EventDataWriter(context);            
+            return (DataWriter<T>)new DataWriterImpl<XMLEventWriter>(context);           
         } else if (c == Node.class) {
-            return (DataWriter<T>)new NodeDataWriter(context);
+            return (DataWriter<T>)new DataWriterImpl<Node>(context);      
         }
         
         return null;
@@ -144,11 +144,11 @@
     public <T> DataReader<T> createReader(Class<T> c) {
         DataReader<T> dr = null;
         if (c == XMLStreamReader.class) {
-            dr = (DataReader<T>)new XMLStreamDataReader(context);
+            dr = (DataReader<T>)new DataReaderImpl<XMLStreamReader>(context);
         } else if (c == XMLEventReader.class) {
-            dr = (DataReader<T>)new EventDataReader(context);
+            dr = (DataReader<T>)new DataReaderImpl<XMLEventReader>(context);
         } else if (c == Node.class) {
-            dr = (DataReader<T>)new NodeDataReader(context);
+            dr = (DataReader<T>)new DataReaderImpl<Node>(context);
         }
         
         // TODO Auto-generated method stub

Modified: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java (original)
+++ incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java Tue Jun 12 15:49:08 2007
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.jaxb;
 
+import java.io.OutputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.ParameterizedType;
@@ -101,6 +102,7 @@
                 // The Marshaller.JAXB_FRAGMENT will tell the Marshaller not to
                 // generate the xml declaration.
                 u.setProperty(Marshaller.JAXB_FRAGMENT, true);
+                u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
             } catch (javax.xml.bind.PropertyException e) {
                 // intentionally empty.
             }
@@ -132,12 +134,14 @@
             if (am != null) {
                 u.setAttachmentMarshaller(am);
             }
-            if (source instanceof Node) {
+            if (source instanceof XMLStreamWriter) {
+                u.marshal(mObj, (XMLStreamWriter)source);
+            } else if (source instanceof OutputStream) {
+                u.marshal(mObj, (OutputStream)source);
+            } else if (source instanceof Node) {
                 u.marshal(mObj, (Node)source);
             } else if (source instanceof XMLEventWriter) {
                 u.marshal(mObj, (XMLEventWriter)source);
-            } else if (source instanceof XMLStreamWriter) {
-                u.marshal(mObj, (XMLStreamWriter)source);
             } else {
                 throw new Fault(new Message("UNKNOWN_SOURCE", BUNDLE, source.getClass().getName()));
             }

Added: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java?view=auto&rev=546656
==============================================================================
--- incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java (added)
+++ incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java Tue Jun 12 15:49:08 2007
@@ -0,0 +1,49 @@
+/**
+ * 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.jaxb.io;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.databinding.DataReader;
+import org.apache.cxf.jaxb.JAXBDataBase;
+import org.apache.cxf.jaxb.JAXBEncoderDecoder;
+import org.apache.cxf.service.model.MessagePartInfo;
+
+public class DataReaderImpl<T> extends JAXBDataBase implements DataReader<T> {
+    public DataReaderImpl(JAXBContext ctx) {
+        setJAXBContext(ctx);
+    }
+
+    public Object read(T input) {
+        return read(null, input);
+    }
+
+    public Object read(MessagePartInfo part, T reader) {
+        return JAXBEncoderDecoder.unmarshall(getJAXBContext(), getSchema(), reader, part, 
+                                             getAttachmentUnmarshaller(), unwrapJAXBElement);
+    }
+
+    public Object read(QName name, T input, Class type) {
+        return JAXBEncoderDecoder.unmarshall(getJAXBContext(), getSchema(), input, name, type, 
+                                             getAttachmentUnmarshaller(), unwrapJAXBElement);
+    }
+
+}

Propchange: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataReaderImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java?view=auto&rev=546656
==============================================================================
--- incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java (added)
+++ incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java Tue Jun 12 15:49:08 2007
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxb.io;
+
+import javax.xml.bind.JAXBContext;
+
+import org.apache.cxf.databinding.DataWriter;
+import org.apache.cxf.jaxb.JAXBDataBase;
+import org.apache.cxf.jaxb.JAXBEncoderDecoder;
+import org.apache.cxf.service.model.MessagePartInfo;
+
+public class DataWriterImpl<T> extends JAXBDataBase implements DataWriter<T> {
+
+    public DataWriterImpl(JAXBContext ctx) {
+        setJAXBContext(ctx);
+    }
+    
+    public void write(Object obj, T output) {
+        write(obj, null, output);
+    }
+    
+    public void write(Object obj, MessagePartInfo part, T output) {
+        if (obj != null) {
+            JAXBEncoderDecoder.marshall(getJAXBContext(), getSchema(), obj, part, output, 
+                                        getAttachmentMarrshaller());
+        }
+    }
+}

Propchange: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/io/DataWriterImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBDataBindingTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBDataBindingTest.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBDataBindingTest.java (original)
+++ incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBDataBindingTest.java Tue Jun 12 15:49:08 2007
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.jaxb;
 
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -44,12 +45,8 @@
 import org.apache.cxf.databinding.DataReader;
 import org.apache.cxf.databinding.DataWriter;
 import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.jaxb.io.EventDataReader;
-import org.apache.cxf.jaxb.io.EventDataWriter;
-import org.apache.cxf.jaxb.io.NodeDataReader;
-import org.apache.cxf.jaxb.io.NodeDataWriter;
-import org.apache.cxf.jaxb.io.XMLStreamDataReader;
-import org.apache.cxf.jaxb.io.XMLStreamDataWriter;
+import org.apache.cxf.jaxb.io.DataReaderImpl;
+import org.apache.cxf.jaxb.io.DataWriterImpl;
 import org.apache.cxf.service.model.SchemaInfo;
 import org.apache.cxf.service.model.ServiceInfo;
 import org.apache.cxf.transport.DestinationFactoryManager;
@@ -152,13 +149,13 @@
     @Test
     public void testCreateReader() {
         DataReader reader = jaxbDataBinding.createReader(XMLStreamReader.class);
-        assertTrue(reader instanceof XMLStreamDataReader);
+        assertTrue(reader instanceof DataReaderImpl);
         
         reader = jaxbDataBinding.createReader(XMLEventReader.class);
-        assertTrue(reader instanceof EventDataReader);
+        assertTrue(reader instanceof DataReaderImpl);
 
         reader = jaxbDataBinding.createReader(Node.class);
-        assertTrue(reader instanceof NodeDataReader);
+        assertTrue(reader instanceof DataReaderImpl);
 
         reader = jaxbDataBinding.createReader(null);
         assertNull(reader);
@@ -168,10 +165,11 @@
     public void testSupportedFormats() {
         List<Class<?>> cls = Arrays.asList(jaxbDataBinding.getSupportedWriterFormats());
         assertNotNull(cls);
-        assertEquals(3, cls.size());
+        assertEquals(4, cls.size());
         assertTrue(cls.contains(XMLStreamWriter.class));
         assertTrue(cls.contains(XMLEventWriter.class));
         assertTrue(cls.contains(Node.class));
+        assertTrue(cls.contains(OutputStream.class));
 
         cls = Arrays.asList(jaxbDataBinding.getSupportedReaderFormats());
         assertNotNull(cls);
@@ -184,13 +182,13 @@
     @Test
     public void testCreateWriter() {
         DataWriter writer = jaxbDataBinding.createWriter(XMLStreamWriter.class);
-        assertTrue(writer instanceof XMLStreamDataWriter);
+        assertTrue(writer instanceof DataWriterImpl);
         
         writer = jaxbDataBinding.createWriter(XMLEventWriter.class);
-        assertTrue(writer instanceof EventDataWriter);
+        assertTrue(writer instanceof DataWriterImpl);
         
         writer = jaxbDataBinding.createWriter(Node.class);
-        assertTrue(writer instanceof NodeDataWriter);
+        assertTrue(writer instanceof DataWriterImpl);
         
         writer = jaxbDataBinding.createWriter(null);
         assertNull(writer);

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java Tue Jun 12 15:49:08 2007
@@ -159,7 +159,10 @@
  
                 } else {
                     soapFault.setFaultCode(new QName("http://cxf.apache.org/faultcode", "HandlerFault"));
-                    soapFault.setFaultString(ex.getMessage());
+                    String msg = ex.getMessage();
+                    if (msg != null) {
+                        soapFault.setFaultString(msg);
+                    }
                 }      
   
                 SOAPFaultException  exception = new SOAPFaultException(soapFault);

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerFaultOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerFaultOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerFaultOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerFaultOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -28,6 +28,9 @@
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.ws.Binding;
 
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.XMLUtils;
 import org.apache.cxf.interceptor.Fault;
@@ -63,7 +66,9 @@
         try {
             
             XMLStreamWriter origWriter = message.getContent(XMLStreamWriter.class);
-            W3CDOMStreamWriter writer = new W3CDOMStreamWriter(XMLUtils.newDocument());
+            Document doc = XMLUtils.newDocument();
+            message.setContent(Node.class, doc);
+            W3CDOMStreamWriter writer = new W3CDOMStreamWriter(doc);
         
             // Replace stax writer with DomStreamWriter
             message.setContent(XMLStreamWriter.class, writer);
@@ -102,6 +107,7 @@
             } else if (domWriter.getDocument().getDocumentElement() != null) {
                 Source source = new DOMSource(domWriter.getDocument());
                 message.setContent(Source.class, source);
+                message.setContent(Node.class, domWriter.getDocument());
                 message.setContent(XMLStreamReader.class, 
                                    StaxUtils.createXMLStreamReader(domWriter.getDocument()));
             }

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -28,6 +28,9 @@
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.ws.Binding;
 
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.XMLUtils;
 import org.apache.cxf.interceptor.Fault;
@@ -62,7 +65,9 @@
         try {
             
             XMLStreamWriter origWriter = message.getContent(XMLStreamWriter.class);
-            W3CDOMStreamWriter writer = new W3CDOMStreamWriter(XMLUtils.newDocument());
+            Document document = XMLUtils.newDocument();
+            message.setContent(Node.class, document);
+            W3CDOMStreamWriter writer = new W3CDOMStreamWriter(document);
         
             // Replace stax writer with DomStreamWriter
             message.setContent(XMLStreamWriter.class, writer);        

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutInterceptor.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/DispatchOutInterceptor.java Tue Jun 12 15:49:08 2007
@@ -61,6 +61,8 @@
         Service.Mode m = message.getExchange().get(Service.Mode.class);
         OutputStream os = message.getContent(OutputStream.class);
         Object obj = message.getContent(Object.class);
+        org.apache.cxf.service.Service service = 
+            message.getExchange().get(org.apache.cxf.service.Service.class);
         
         if (obj == null) {
             throw new Fault(new org.apache.cxf.common.i18n.Message("DISPATCH_OBJECT_CANNOT_BE_NULL", LOG));
@@ -79,7 +81,7 @@
                     }
                 } else if (m == Service.Mode.PAYLOAD) {
                     SOAPMessage msg = initSOAPMessage();
-                    DataWriter<Node> dataWriter = getDataWriter(message, Node.class);
+                    DataWriter<Node> dataWriter = getDataWriter(message, service, Node.class);
                     if (obj instanceof SOAPMessage || obj instanceof DataSource) {
                         throw new RuntimeException(obj.getClass()
                                                    + " is not valid in PAYLOAD mode with SOAP/HTTP");
@@ -102,7 +104,9 @@
                 if (obj instanceof Source || obj instanceof DataSource) {
                     doTransform(obj, os);
                 } else {
-                    DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, XMLStreamWriter.class);
+                    DataWriter<XMLStreamWriter> dataWriter = getDataWriter(message, 
+                                                                           service, 
+                                                                           XMLStreamWriter.class);
                     XMLStreamWriter xmlWriter = message.getContent(XMLStreamWriter.class);
                     if (xmlWriter == null) {
                         xmlWriter = StaxUtils.createXMLStreamWriter(os, "UTF-8");

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptorTest.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptorTest.java Tue Jun 12 15:49:08 2007
@@ -60,7 +60,7 @@
 import org.apache.cxf.headers.Header;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.interceptor.InterceptorChain;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.jaxws.handler.AbstractProtocolHandlerInterceptor;
 import org.apache.cxf.jaxws.handler.HandlerChainInvoker;
 import org.apache.cxf.message.Exchange;
@@ -558,7 +558,7 @@
         return os;
     }*/
 
-    private class CachedStream extends AbstractCachedOutputStream {
+    private class CachedStream extends CachedOutputStream {
         protected void doFlush() throws IOException {
             currentStream.flush();
         }

Modified: incubator/cxf/trunk/rt/transports/http-jetty/src/test/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestinationTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http-jetty/src/test/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestinationTest.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/transports/http-jetty/src/test/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestinationTest.java (original)
+++ incubator/cxf/trunk/rt/transports/http-jetty/src/test/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestinationTest.java Tue Jun 12 15:49:08 2007
@@ -19,7 +19,6 @@
 
 package org.apache.cxf.transport.http_jetty;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URL;
@@ -40,7 +39,7 @@
 import org.apache.cxf.configuration.security.AuthorizationPolicy;
 import org.apache.cxf.endpoint.EndpointResolverRegistry;
 import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.io.AbstractCachedOutputStream;
+import org.apache.cxf.io.AbstractWrappedOutputStream;
 import org.apache.cxf.message.ExchangeImpl;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageImpl;
@@ -65,6 +64,7 @@
 import org.mortbay.jetty.HttpFields;
 import org.mortbay.jetty.Request;
 import org.mortbay.jetty.Response;
+
 import static org.apache.cxf.ws.addressing.JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_INBOUND;
 
 public class JettyHTTPDestinationTest extends Assert {
@@ -747,6 +747,8 @@
                                        Message outMsg,
                                        int status,
                                        boolean oneway) throws Exception {
+        outMsg.getExchange().setOneWay(oneway);
+
         assertTrue("unexpected back channel type",
                    backChannel instanceof JettyHTTPDestination.BackChannelConduit);
         assertTrue("unexpected content formats",
@@ -754,18 +756,13 @@
         OutputStream responseOS = outMsg.getContent(OutputStream.class);
         assertNotNull("expected output stream", responseOS);
         assertTrue("unexpected output stream type",
-                   responseOS instanceof AbstractCachedOutputStream);
+                   responseOS instanceof AbstractWrappedOutputStream);
                
         outMsg.put(Message.RESPONSE_CODE, status);          
         responseOS.write(PAYLOAD.getBytes());
         
         setUpResponseHeaders(outMsg);
         
-        OutputStream underlyingOS =
-            ((AbstractCachedOutputStream)responseOS).getOut();
-        assertTrue("unexpected underlying output stream type",
-                   underlyingOS instanceof ByteArrayOutputStream);
-        outMsg.getExchange().setOneWay(oneway);
         responseOS.flush();        
         assertEquals("unexpected status",
                      status,
@@ -775,11 +772,8 @@
                          "Internal Server Error",
                          response.getReason());
         }*/
-        verifyResponseHeaders(outMsg);        
-        underlyingOS = ((AbstractCachedOutputStream)responseOS).getOut();
-        assertFalse("unexpected underlying output stream type: "
-                    + underlyingOS.getClass(),
-                    underlyingOS instanceof ByteArrayOutputStream);
+        verifyResponseHeaders(outMsg);     
+        
         if (oneway) {
             assertNull("unexpected HTTP response",
                        outMsg.get(JettyHTTPDestination.HTTP_RESPONSE));

Modified: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java?view=diff&rev=546656&r1=546655&r2=546656
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/AbstractHTTPDestination.java Tue Jun 12 15:49:08 2007
@@ -374,9 +374,11 @@
     private class WrappedOutputStream extends AbstractWrappedOutputStream {
 
         protected HttpServletResponse response;
-
+        private Message outMessage;
+        
         WrappedOutputStream(Message m, HttpServletResponse resp) {
-            super(m);
+            super();
+            this.outMessage = m;
             response = resp;
         }
 
@@ -384,17 +386,23 @@
          * Perform any actions required on stream flush (freeze headers,
          * reset output stream ... etc.)
          */
-        protected void doFlush() throws IOException {
+        protected void onFirstWrite() throws IOException {
             OutputStream responseStream = flushHeaders(outMessage);
-            if (null != responseStream && !alreadyFlushed()) {
-                resetOut(responseStream, true);
+            if (null != responseStream) {
+                wrappedStream = responseStream;
             }
         }
 
         /**
          * Perform any actions required on stream closure (handle response etc.)
          */
-        protected void doClose() {
+        protected void doClose() throws IOException {
+            if (wrappedStream == null) {
+                OutputStream responseStream = flushHeaders(outMessage);
+                if (null != responseStream) {
+                    wrappedStream = responseStream;
+                }
+            }
             commitResponse();
         }
 



Re: svn commit: r546656 [1/2] - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/io/ api/src/main/java/org/apache/cxf/message/ api/src/main/java/org/apache/cxf/phase/ common/common/src/main/java/org/apache/cxf/helpers/ rt/bindings/http/src/main/ja...

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

>Author: dandiep
>Date: Tue Jun 12 15:49:08 2007
>New Revision: 546656
>
>URL: http://svn.apache.org/viewvc?view=rev&rev=546656
>Log:
>
>Refactoring of the low level IO layer inside CXF.
>
>Remove the dependence on flush() being called ONCE and only once
>inside CXF. There was the assumption in all the code that things would 
>be cached until we actually finished databinding, which is a bad assumption. 
>There are a couple problems with this: 
>1. The Soap envelope writer was writing the envelope twice if a fault was 
>thrown during databinding and the stream was already flushed. (i.e. during
>validation)
>2. The code didn't differentiate between the type of caching that was going
>on. i.e. are we a) writing to the underlying stream AND caching the message
>at the same time. Or b) are we caching the message and then writing on close()
>
>Ensure that the RM and Logging layers correctly do their work on close() 
>instead of flush(). 
>
>Transports now pass in the underlying stream. The RM layer and logging
>interceptors correct detect when a cached stream is not being used
>and act accordingly. This is much more robust as I/O transformations
>are a very valid use case an many people will want to switch the 
>underlying streams. We also shouldn't force transport writers to 
>use CachedOutputStream. 
>
>Rename AbstractCachedOutputStream to CachedOutputStream and make
>it a non-abstract class. This cuts down on the number of CachedOutputStream
>classes laying around! There are now two extended implementations of
>COS as well:
>1. WriteOnCloseOutputStream. This caches the message until the outputstream
>is closed. This is needed for the RM scenarios where we are caching the message
>until the CreateSequence is done. We don't want to open the connection until
>all of this is done. (I think we could probably reset this output stream 
>as soon as the createsequence is finished though
>  
>
Hi Dan,

I am not sure what you mean with 'caching the message until the 
CreateSequence is done':
In the RM case the original application message should not be written 
before a Sequence is available - the logical RM out interceptor (which 
triggers sequence creation) sits in the PRE_LOGICAL phase
RM uses the RetransmissionCallback class to cache application messages 
for future resends  - util they are acknowledged.

Andrea.

>2. CacheAndWriteOutputStream. This caches the message while it is written
>to the underlying stream at the same time. Useful for logging.
>
>Update the DataBinding code to have JAXB write directly to the OutputStream
>whenever possible. This gives a great performance improvement for some scenarios.
>
>Refactor the JAXB code so we don't have so many data readers/writers.
>
>TODO: Make RM and Logging work when the message is larger than memory or the 
>CachedOutputStream writes to disk.
>  
>
>TODO: Fix HTTPS 401 Redirect test 
>
>
>  
>

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland