You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by jl...@apache.org on 2007/04/06 04:36:45 UTC

svn commit: r526034 - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/interceptor/ api/src/main/java/org/apache/cxf/phase/ api/src/test/java/org/apache/cxf/phase/ rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/ rt/bind...

Author: jliu
Date: Thu Apr  5 19:36:43 2007
New Revision: 526034

URL: http://svn.apache.org/viewvc?view=rev&rev=526034
Log:
CXF-411: refactor interceptor chain API to use ending interceptors instead of sub-chain.

Modified:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/interceptor/InterceptorChain.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/Phase.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
    incubator/cxf/trunk/api/src/test/java/org/apache/cxf/phase/PhaseInterceptorChainTest.java
    incubator/cxf/trunk/rt/bindings/http/src/main/java/org/apache/cxf/binding/http/interceptor/DatabindingOutSetupInterceptor.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/bindings/soap/src/main/java/org/apache/cxf/binding/soap/saaj/SAAJOutInterceptor.java
    incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestBase.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.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/MessageSenderInterceptor.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/interceptor/WrappedOutInterceptor.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/phase/PhaseManagerImpl.java
    incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/BareOutInterceptorTest.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptorTest.java

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/interceptor/InterceptorChain.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/interceptor/InterceptorChain.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/interceptor/InterceptorChain.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/interceptor/InterceptorChain.java Thu Apr  5 19:36:43 2007
@@ -31,8 +31,6 @@
         EXECUTING,
         COMPLETE,
         ABORTED,
-        SUBCHAIN_EXECUTING,
-        SUBCHAIN_COMPLETE
     };
     
     String STARTING_AFTER_INTERCEPTOR_ID = "starting_after_interceptor_id";
@@ -44,16 +42,12 @@
     boolean doIntercept(Message message);
     
     boolean doIntercept(Message message, String startingAfterInterceptorID);
-
-    boolean doInterceptInSubChain(Message message);    
   
     void pause();
     
     void resume();
     
     void reset();
-    
-    void finishSubChain();
     
     ListIterator<Interceptor<? extends Message>> getIterator();
 

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/Phase.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/Phase.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/Phase.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/phase/Phase.java Thu Apr  5 19:36:43 2007
@@ -24,20 +24,34 @@
     // can be removed from once defined as default value in configuration metadata for bus
   
     public static final String SETUP = "setup";
+    public static final String SETUP_ENDING = "setup-ending";
     public static final String PRE_LOGICAL = "pre-logical";
+    public static final String PRE_LOGICAL_ENDING = "pre-logical-ending";
     public static final String USER_LOGICAL = "user-logical";
+    public static final String USER_LOGICAL_ENDING = "user-logical-ending";
     public static final String POST_LOGICAL = "post-logical";
+    public static final String POST_LOGICAL_ENDING = "post-logical-ending";
     public static final String MARSHAL = "marshal";
+    public static final String MARSHAL_ENDING = "marshal-ending";
     public static final String PRE_PROTOCOL = "pre-protocol";
+    public static final String PRE_PROTOCOL_ENDING = "pre-protocol-ending";
     public static final String USER_PROTOCOL = "user-protocol";
+    public static final String USER_PROTOCOL_ENDING = "user-protocol-ending";
     public static final String POST_PROTOCOL = "post-protocol";
+    public static final String POST_PROTOCOL_ENDING = "post-protocol-ending";
     public static final String PREPARE_SEND = "prepare-send";
+    public static final String PREPARE_SEND_ENDING = "prepare-send-ending";
     public static final String PRE_STREAM = "pre-stream";
+    public static final String PRE_STREAM_ENDING = "pre-stream-ending";
     public static final String USER_STREAM = "user-stream";
+    public static final String USER_STREAM_ENDING = "user-stream-ending";
     public static final String POST_STREAM = "post-stream";
+    public static final String POST_STREAM_ENDING = "post-stream-ending";
     public static final String WRITE = "write";
+    public static final String WRITE_ENDING = "write-ending";
     public static final String SEND = "send";
-    
+    public static final String SEND_ENDING = "send-ending";
+   
     public static final String RECEIVE = "receive";
     public static final String READ = "read";
     public static final String PROTOCOL = "protocol";

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -27,7 +27,6 @@
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
-import java.util.Stack;
 import java.util.TreeMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -61,7 +60,6 @@
     private final Map<String, List<Interceptor>> nameMap = new HashMap<String, List<Interceptor>>();
 
     private State state;
-    private Stack<State> subChainState;
     private PhaseInterceptorIterator iterator;
     private Message pausedMessage;
     private MessageObserver faultObserver;
@@ -73,8 +71,7 @@
     
     public PhaseInterceptorChain(List<Phase> ps) {
         state = State.EXECUTING;
-        subChainState = new Stack<State>();
-
+ 
         for (Phase phase : ps) {
             List<Interceptor> ints = new ArrayList<Interceptor>();
             interceptors.put(phase, ints);
@@ -124,13 +121,6 @@
         state = State.PAUSED;
     }
 
-    public void finishSubChain() {
-        if (!subChainState.isEmpty()) {
-            subChainState.pop();
-            subChainState.push(State.SUBCHAIN_COMPLETE);
-        }
-    }
-
     public void resume() {
         if (state == State.PAUSED) {
             state = State.EXECUTING;
@@ -165,17 +155,11 @@
                 if (LOG.isLoggable(Level.FINE)) {
                     LOG.fine("Invoking handleMessage on interceptor " + currentInterceptor);
                 }
+                
                 currentInterceptor.handleMessage(message);
                 
-                if (!subChainState.empty() && subChainState.peek() == State.SUBCHAIN_COMPLETE) {
-                    return true;
-                }
             } catch (RuntimeException ex) {
                 if (!faultOccured) {
-                    if (subChainState.size() > 0 
-                        && subChainState.peek().equals(State.EXECUTING)) {
-                        throw ex;
-                    }
  
                     faultOccured = true;
                     if (LOG.isLoggable(Level.INFO)) {
@@ -222,21 +206,6 @@
             }
         }
         return doIntercept(message);
-    }
-    
-    /**
-     * Invokes the following inteceptors in a sub chain until the last chain in the
-     * sub chain calls finishSubChain, which makes the flow continue in the
-     * main chain.
-     * 
-     * @param message the message
-     * @throws Exception
-     */
-    public boolean doInterceptInSubChain(Message message) {
-        subChainState.push(State.SUBCHAIN_EXECUTING);
-        boolean result = doIntercept(message);
-        subChainState.pop();
-        return result;
     }
 
     public void reset() {

Modified: incubator/cxf/trunk/api/src/test/java/org/apache/cxf/phase/PhaseInterceptorChainTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/test/java/org/apache/cxf/phase/PhaseInterceptorChainTest.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/api/src/test/java/org/apache/cxf/phase/PhaseInterceptorChainTest.java (original)
+++ incubator/cxf/trunk/api/src/test/java/org/apache/cxf/phase/PhaseInterceptorChainTest.java Thu Apr  5 19:36:43 2007
@@ -283,52 +283,10 @@
         assertEquals(1, p3.invoked);
     }
 
-    public void testSubChainInvocation() throws Exception {
-        SubChainPhaseInterceptor p1 = new SubChainPhaseInterceptor("phase1",
-                "p1");
-        EndOfSubChainPhaseInterceptor p2 = new EndOfSubChainPhaseInterceptor(
-                "phase2", "p2");
-        CountingPhaseInterceptor p3 = new CountingPhaseInterceptor("phase3",
-                "p3");
-
-        message.getInterceptorChain();
-        EasyMock.expectLastCall().andReturn(chain).anyTimes();
-
-        control.replay();
-        chain.add(p1);
-        chain.add(p2);
-        chain.add(p3);
-        chain.doIntercept(message);
-        assertEquals(1, p1.invoked);
-        assertEquals(1, p2.invoked);
-        assertEquals(1, p3.invoked);
-    }
-
-    public void testSubChainInvocationWithoutEnteringSubChain() throws Exception {
-        CountingPhaseInterceptor p1 = new CountingPhaseInterceptor("phase1",
-                "p1");
-        EndOfSubChainPhaseInterceptor p2 = new EndOfSubChainPhaseInterceptor(
-                "phase2", "p2");
-        CountingPhaseInterceptor p3 = new CountingPhaseInterceptor("phase3",
-                "p3");
-
-        message.getInterceptorChain();
-        EasyMock.expectLastCall().andReturn(chain).anyTimes();
-
-        control.replay();
-        chain.add(p1);
-        chain.add(p2);
-        chain.add(p3);
-        chain.doIntercept(message);
-        assertEquals(1, p1.invoked);
-        assertEquals(1, p2.invoked);
-        assertEquals(1, p3.invoked);
-    }
-
     public void testChainInvocationStartFromSpecifiedInterceptor() throws Exception {
         CountingPhaseInterceptor p1 = new CountingPhaseInterceptor("phase1",
                 "p1");
-        EndOfSubChainPhaseInterceptor p2 = new EndOfSubChainPhaseInterceptor(
+        CountingPhaseInterceptor p2 = new CountingPhaseInterceptor(
                 "phase2", "p2");
         CountingPhaseInterceptor p3 = new CountingPhaseInterceptor("phase3",
                 "p3");
@@ -435,34 +393,5 @@
         }
     }
 
-    public class SubChainPhaseInterceptor extends
-            AbstractPhaseInterceptor<Message> {
-        int invoked;
-
-        public SubChainPhaseInterceptor(String phase, String id) {
-            setPhase(phase);
-            setId(id);
-        }
-
-        public void handleMessage(Message m) {
-            invoked++;
-            m.getInterceptorChain().doInterceptInSubChain(m);
-        }
-    }
-
-    public class EndOfSubChainPhaseInterceptor extends
-            AbstractPhaseInterceptor<Message> {
-        int invoked;
-
-        public EndOfSubChainPhaseInterceptor(String phase, String id) {
-            setPhase(phase);
-            setId(id);
-        }
-
-        public void handleMessage(Message m) {
-            invoked++;
-            m.getInterceptorChain().finishSubChain();
-        }
-    }
 
 }

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -80,7 +80,7 @@
             boolean putOrPost = verb.equals(HttpConstants.POST) || verb.equals(HttpConstants.PUT);
             
             if (putOrPost) { 
-                chain.doInterceptInSubChain(message);
+                chain.doIntercept(message);
                 chain.add(new URIParameterOutInterceptor());
                 chain.add(new DocumentWriterInterceptor());
                 chain.add(STAX_OUT);

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -96,7 +96,6 @@
             }
             // Finishing the writing.
             xmlWriter.writeEndElement();            
-            message.getInterceptorChain().finishSubChain();
         } catch (XMLStreamException e) {
             throw new Fault(e);
         }

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -81,21 +81,14 @@
                                   soapVersion.getBody().getLocalPart(),
                                   soapVersion.getNamespace());
             
-            // Calling for Wrapped/RPC/Doc/ Interceptor for writing SOAP body
-            //message.getInterceptorChain().doIntercept(message);            
-            message.getInterceptorChain().doInterceptInSubChain(message);
-            
-            xtw.writeEndElement();            
-            // Write Envelope end element
-            xtw.writeEndElement();
-            xtw.writeEndDocument();
-            
-            xtw.flush();
-            
+            // Interceptors followed such as Wrapped/RPC/Doc Interceptor will write SOAP body
         } catch (XMLStreamException e) {
             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) {
@@ -204,4 +197,30 @@
 
         return dataWriter;
     }
+        
+    public class SoapOutEndingInterceptor extends AbstractSoapInterceptor {
+        public SoapOutEndingInterceptor() {
+            super();
+            setPhase(Phase.WRITE_ENDING);
+        }
+
+        public void handleMessage(SoapMessage message) throws Fault {
+            SoapVersion soapVersion = message.getVersion();
+            try {
+                XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class);
+                if (xtw != null) {
+                    xtw.writeEndElement();            
+                    // Write Envelope end element
+                    xtw.writeEndElement();
+                    xtw.writeEndDocument();
+                    
+                    xtw.flush();
+                }
+            } catch (XMLStreamException e) {
+                throw new SoapFault(new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), e,
+                                    soapVersion.getSender());
+            }
+        }
+
+    }    
 }

Modified: incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/saaj/SAAJOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/saaj/SAAJOutInterceptor.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/saaj/SAAJOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/saaj/SAAJOutInterceptor.java Thu Apr  5 19:36:43 2007
@@ -55,8 +55,8 @@
         setPhase(Phase.PRE_PROTOCOL);
     }
     
-    public void handleMessage(SoapMessage cxfMessage) throws Fault {
-        SoapVersion version = cxfMessage.getVersion();
+    public void handleMessage(SoapMessage message) throws Fault {
+        SoapVersion version = message.getVersion();
         try {
             MessageFactory factory = null;
             if (version.getVersion() == 1.1) {
@@ -64,45 +64,44 @@
             } else {
                 factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
             }
-            SOAPMessage message = factory.createMessage();
+            SOAPMessage soapMessage = factory.createMessage();
 
-            SOAPPart soapPart = message.getSOAPPart();
+            SOAPPart soapPart = soapMessage.getSOAPPart();
             W3CDOMStreamWriter writer = new W3CDOMStreamWriter(soapPart);
             // Replace stax writer with DomStreamWriter
-            cxfMessage.setContent(XMLStreamWriter.class, writer);
-            cxfMessage.setContent(SOAPMessage.class, message);
+            message.setContent(XMLStreamWriter.class, writer);
+            message.setContent(SOAPMessage.class, soapMessage);
         } catch (SOAPException e) {
             throw new SoapFault(new Message("SOAPEXCEPTION", BUNDLE), e, version.getSender());
         }
         
-        // Add a final interceptor to write the message
-        cxfMessage.getInterceptorChain().add(new AbstractSoapInterceptor() {
+        // Add a final interceptor to write the message        
+        message.getInterceptorChain().add(new SAAJOutEndingInterceptor());
+    }
+    
+    public class SAAJOutEndingInterceptor extends AbstractSoapInterceptor {
+        public SAAJOutEndingInterceptor() {
+            super();
+            setPhase(Phase.PRE_PROTOCOL_ENDING);
+        }
 
-            @Override
-            public String getPhase() {
-                return Phase.SEND;
-            }
+        public void handleMessage(SoapMessage message) throws Fault {
+            SOAPMessage soapMessage = message.getContent(SOAPMessage.class);
 
-            public void handleMessage(SoapMessage message) throws Fault {
-                SOAPMessage soapMessage = message.getContent(SOAPMessage.class);
-                
-                if (soapMessage != null) {
-                    OutputStream os = message.getContent(OutputStream.class);
-                    try {
-                        soapMessage.writeTo(os);
-                        os.flush();
-                    } catch (IOException e) {
-                        throw new SoapFault(new Message("SOAPEXCEPTION", BUNDLE), e, 
-                                            message.getVersion().getSender());
-                    } catch (SOAPException e) {
-                        throw new SoapFault(new Message("SOAPEXCEPTION", BUNDLE), e, 
-                                            message.getVersion().getSender());
-                    }
+            if (soapMessage != null) {
+                OutputStream os = message.getContent(OutputStream.class);
+                try {
+                    soapMessage.writeTo(os);
+                    os.flush();
+                } catch (IOException e) {
+                    throw new SoapFault(new Message("SOAPEXCEPTION", BUNDLE), e, message.getVersion()
+                        .getSender());
+                } catch (SOAPException e) {
+                    throw new SoapFault(new Message("SOAPEXCEPTION", BUNDLE), e, message.getVersion()
+                        .getSender());
                 }
             }
-            
-        });
-       
-    }
+        }
 
+    }
 }

Modified: incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestBase.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestBase.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestBase.java (original)
+++ incubator/cxf/trunk/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/TestBase.java Thu Apr  5 19:36:43 2007
@@ -61,9 +61,11 @@
         Phase phase1 = new Phase("phase1", 1);
         Phase phase2 = new Phase("phase2", 2);
         Phase phase3 = new Phase("phase3", 3);
+        Phase phase4 = new Phase(Phase.WRITE_ENDING, 4);
         phases.add(phase1);
         phases.add(phase2);
         phases.add(phase3);
+        phases.add(phase4);
         chain = new PhaseInterceptorChain(phases);
 
         soapMessage = TestUtil.createEmptySoapMessage(Soap11.getInstance(), chain);

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/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=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/AttachmentOutInterceptor.java Thu Apr  5 19:36:43 2007
@@ -37,7 +37,7 @@
         setPhase(Phase.PRE_STREAM);
     }
 
-    public void handleMessage(Message message) throws Fault {
+    public void handleMessage(Message message) {
         if (!Boolean.TRUE.equals(message.getContextualProperty(
                 org.apache.cxf.message.Message.MTOM_ENABLED))) {
             return;
@@ -46,13 +46,31 @@
         AttachmentSerializer serializer = new AttachmentSerializer(message);
         try {
             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);
-        }
+        }        
+        message.setContent(AttachmentSerializer.class, serializer);
+        
+        // Add a final interceptor to write attachements
+        message.getInterceptorChain().add(new AttachmentOutEndingInterceptor());   
     }
+    
+    public class AttachmentOutEndingInterceptor extends AbstractPhaseInterceptor<Message> {
+        public AttachmentOutEndingInterceptor() {
+            super();
+            setPhase(Phase.PRE_STREAM_ENDING);
+        }
 
+        public void handleMessage(Message message) {
+            AttachmentSerializer ser = message.getContent(AttachmentSerializer.class);
+            if (ser != null) {
+                try {
+                    ser.writeAttachments();
+                } catch (IOException e) {
+                    throw new Fault(new org.apache.cxf.common.i18n.Message("WRITE_ATTACHMENTS", BUNDLE), e);
+                }
+            }
+        }
+
+    }
 }

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -74,7 +74,6 @@
                 }
             }
         }
-        message.getInterceptorChain().finishSubChain();
     }
     
 }

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java Thu Apr  5 19:36:43 2007
@@ -54,20 +54,33 @@
 
         try {
             conduit.prepare(message);
-
-            if (message.getInterceptorChain().doIntercept(message)) {
-                conduit.close(message);
-            } else {
-                if (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));
-                    }
-                }
-            }
         } catch (IOException ex) {
             throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), ex);
+        }    
+        
+        // Add a final interceptor to close the conduit
+        message.getInterceptorChain().add(new MessageSenderEndingInterceptor());
+    }
+    
+    public class MessageSenderEndingInterceptor extends AbstractPhaseInterceptor<Message> {
+        public MessageSenderEndingInterceptor() {
+            super();
+            setPhase(Phase.PREPARE_SEND_ENDING);
+        }
+
+        public void handleMessage(Message message) throws Fault {
+            Exchange ex = message.getExchange();
+            Conduit endingConduit = 
+                message.getConduit() != null
+                ? message.getConduit() : ex.getConduit() != null
+                    ? ex.getConduit() : (ex.getOutMessage() != null || ex.getOutFaultMessage() != null)
+                        ? OutgoingChainInterceptor.getBackChannelConduit(ex) : null;
+            try {
+                endingConduit.close(message);
+            } catch (IOException e) {
+                throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), e);
+            }
         }
     }
+
 }

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -35,6 +35,7 @@
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.staxutils.StaxUtils;
 
+
 /**
  * Creates an XMLStreamReader from the InputStream on the Message.
  */
@@ -74,28 +75,10 @@
         } catch (XMLStreamException e) {
             throw new Fault(new org.apache.cxf.common.i18n.Message("STREAM_CREATE_EXC", BUNDLE), e);
         }
-
         message.setContent(XMLStreamWriter.class, writer);
 
-        boolean result = message.getInterceptorChain().doIntercept(message);
-        
-        try {
-            XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class);
-            if (xtw != null) {
-                xtw.writeEndDocument();
-                xtw.close();
-            }
-            
-            if (!result && 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));
-                }
-            }            
-        } catch (XMLStreamException e) {
-            throw new Fault(new org.apache.cxf.common.i18n.Message("STAX_WRITE_EXC", BUNDLE), e);
-        }
+        // Add a final interceptor to write end elements
+        message.getInterceptorChain().add(new StaxOutEndingInterceptor());
     }
 
     public static XMLOutputFactory getXMLOutputFactory(Message m) throws Fault {
@@ -133,4 +116,25 @@
             return StaxUtils.getXMLOutputFactory();
         }
     }
+    
+    public class StaxOutEndingInterceptor extends AbstractPhaseInterceptor<Message> {
+        public StaxOutEndingInterceptor() {
+            super();
+            setPhase(Phase.PRE_STREAM_ENDING);
+            getAfter().add(AttachmentOutInterceptor.AttachmentOutEndingInterceptor.class.getName());
+        }
+
+        public void handleMessage(Message message) throws Fault {
+            try {
+                XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class);
+                if (xtw != null) {
+                    xtw.writeEndDocument();
+                    xtw.close();
+                }
+            } catch (XMLStreamException e) {
+                throw new Fault(new org.apache.cxf.common.i18n.Message("STAX_WRITE_EXC", BUNDLE), e);
+            }
+        }
+
+    }    
 }

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedOutInterceptor.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/WrappedOutInterceptor.java Thu Apr  5 19:36:43 2007
@@ -45,7 +45,7 @@
         BindingOperationInfo bop = message.getExchange().get(BindingOperationInfo.class);
 
         if (bop != null && bop.isUnwrapped()) {
-            XMLStreamWriter xmlWriter = getXMLStreamWriter(message);
+            XMLStreamWriter xmlWriter = message.getContent(XMLStreamWriter.class);
 
             MessageInfo messageInfo;
             if (isRequestor(message)) {
@@ -53,7 +53,7 @@
             } else {
                 messageInfo = bop.getWrappedOperation().getOperationInfo().getOutput();
             }
-            
+
             MessagePartInfo part = messageInfo.getMessageParts().get(0);
             QName name = part.getConcreteName();
 
@@ -61,15 +61,31 @@
                 xmlWriter.setDefaultNamespace(name.getNamespaceURI());
                 xmlWriter.writeStartElement(name.getNamespaceURI(), name.getLocalPart());
                 xmlWriter.writeDefaultNamespace(name.getNamespaceURI());
-                message.getInterceptorChain().doIntercept(message);
-                xmlWriter.writeEndElement();
             } catch (XMLStreamException e) {
                 throw new Fault(new org.apache.cxf.common.i18n.Message("STAX_WRITE_EXC", BUNDLE), e);
             }
+
+            // Add a final interceptor to write end element
+            message.getInterceptorChain().add(new WrappedOutEndingInterceptor());
         }
     }
+    
+    public class WrappedOutEndingInterceptor extends AbstractOutDatabindingInterceptor {
+        public WrappedOutEndingInterceptor() {
+            super();
+            setPhase(Phase.MARSHAL_ENDING);
+        }
 
-    protected XMLStreamWriter getXMLStreamWriter(Message message) {
-        return message.getContent(XMLStreamWriter.class);
-    }
+        public void handleMessage(Message message) throws Fault {
+            try {
+                XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class);
+                if (xtw != null) {
+                    xtw.writeEndElement();
+                }
+            } catch (XMLStreamException e) {
+                throw new Fault(new org.apache.cxf.common.i18n.Message("STAX_WRITE_EXC", BUNDLE), e);
+            }
+        }
+
+    }  
 }

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/phase/PhaseManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/phase/PhaseManagerImpl.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/phase/PhaseManagerImpl.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/phase/PhaseManagerImpl.java Thu Apr  5 19:36:43 2007
@@ -25,10 +25,10 @@
 import org.apache.cxf.extension.BusExtension;
 
 public class PhaseManagerImpl implements PhaseManager, BusExtension {
- 
+
     private  List<Phase> inPhases;
     private  List<Phase> outPhases;
-   
+
     public PhaseManagerImpl() {
         createInPhases();
         createOutPhases();
@@ -46,18 +46,18 @@
     public List<Phase> getInPhases() {
         return inPhases;
     }
-  
+
     public List<Phase> getOutPhases() {
         return outPhases;
     }
 
     final void createInPhases() {
 
-        inPhases = new ArrayList<Phase>(); 
+        inPhases = new ArrayList<Phase>();
         int i = 0;
-        
+
         inPhases = new ArrayList<Phase>();
-        inPhases.add(new Phase(Phase.RECEIVE, ++i * 1000));        
+        inPhases.add(new Phase(Phase.RECEIVE, ++i * 1000));
         inPhases.add(new Phase(Phase.PRE_STREAM, ++i * 1000));
         inPhases.add(new Phase(Phase.USER_STREAM, ++i * 1000));
         inPhases.add(new Phase(Phase.POST_STREAM, ++i * 1000));
@@ -73,12 +73,12 @@
         inPhases.add(new Phase(Phase.INVOKE, ++i * 1000));
         inPhases.add(new Phase(Phase.POST_INVOKE, ++i * 1000));
     }
-    
+
     final void createOutPhases() {
-        
+
         outPhases = new ArrayList<Phase>();
         int i = 0;
-        
+
         outPhases.add(new Phase(Phase.SETUP, ++i * 1000));
         outPhases.add(new Phase(Phase.PRE_LOGICAL, ++i * 1000));
         outPhases.add(new Phase(Phase.USER_LOGICAL, ++i * 1000));
@@ -87,19 +87,46 @@
 
         outPhases.add(new Phase(Phase.PRE_STREAM, ++i * 1000));
 
-        outPhases.add(new Phase(Phase.PRE_PROTOCOL, ++i * 1000));        
-        
+        outPhases.add(new Phase(Phase.PRE_PROTOCOL, ++i * 1000));
+
         outPhases.add(new Phase(Phase.WRITE, ++i * 1000));
         outPhases.add(new Phase(Phase.MARSHAL, ++i * 1000));
-        
+
         outPhases.add(new Phase(Phase.USER_PROTOCOL, ++i * 1000));
         outPhases.add(new Phase(Phase.POST_PROTOCOL, ++i * 1000));
-        
+
         outPhases.add(new Phase(Phase.USER_STREAM, ++i * 1000));
         outPhases.add(new Phase(Phase.POST_STREAM, ++i * 1000));
-        
+
         outPhases.add(new Phase(Phase.SEND, ++i * 1000));
+
+        //Make sure ending interceptors are put in positions symmetric
+        // to their starting interceptors
+        outPhases.add(new Phase(Phase.SEND_ENDING, ++i * 1000));
         
+        outPhases.add(new Phase(Phase.POST_STREAM_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.USER_STREAM_ENDING, ++i * 1000));
+
+        outPhases.add(new Phase(Phase.POST_PROTOCOL_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.USER_PROTOCOL_ENDING, ++i * 1000));
+
+        outPhases.add(new Phase(Phase.MARSHAL_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.WRITE_ENDING, ++i * 1000));
+
+        outPhases.add(new Phase(Phase.PRE_PROTOCOL_ENDING, ++i * 1000));
+        
+        outPhases.add(new Phase(Phase.PRE_STREAM_ENDING, ++i * 1000));
+
+        outPhases.add(new Phase(Phase.PREPARE_SEND_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.POST_LOGICAL_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.USER_LOGICAL_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.PRE_LOGICAL_ENDING, ++i * 1000));
+        outPhases.add(new Phase(Phase.SETUP_ENDING, ++i * 1000));
+
     }
+
+
+
+
 
 }

Modified: incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/BareOutInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/BareOutInterceptorTest.java?view=diff&rev=526034&r1=526033&r2=526034
==============================================================================
--- incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/BareOutInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/BareOutInterceptorTest.java Thu Apr  5 19:36:43 2007
@@ -57,8 +57,6 @@
         message.getExchange().put(BindingOperationInfo.class, operation);
         IMocksControl control = EasyMock.createNiceControl();
         InterceptorChain ic = control.createMock(InterceptorChain.class);
-        ic.finishSubChain();
-        EasyMock.expectLastCall().anyTimes();
         message.setInterceptorChain(ic);
         control.replay();
     }

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=526034&r1=526033&r2=526034
==============================================================================
--- 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 Thu Apr  5 19:36:43 2007
@@ -146,7 +146,6 @@
                     writer.writeEndElement();
                     
                     writer.flush();
-                    message.getInterceptorChain().finishSubChain();
                 } catch (Exception e) {
                     // do nothing
                 }
@@ -335,7 +334,6 @@
                     writer.writeEndElement();
                     
                     writer.flush();
-                    message.getInterceptorChain().finishSubChain();
                 } catch (Exception e) {
                     // do nothing
                 }