You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by na...@apache.org on 2006/11/17 05:01:19 UTC

svn commit: r476044 - in /webservices/axis2/trunk/java/modules: kernel/src/org/apache/axis2/context/ kernel/src/org/apache/axis2/engine/ kernel/src/org/apache/axis2/handlers/ security/src/org/apache/rampart/handler/

Author: nagy
Date: Thu Nov 16 20:01:19 2006
New Revision: 476044

URL: http://svn.apache.org/viewvc?view=rev&rev=476044
Log:
Ported r462507 and r468825 (Added a method to the handler interface, and the mechanisms to invoke it, to allow handlers to be called after processing of a particular message flow, on which they took part, has completed.) 

Modified:
    webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/context/MessageContext.java
    webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisEngine.java
    webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Handler.java
    webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Phase.java
    webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/handlers/AbstractHandler.java
    webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartReceiver.java
    webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartSender.java
    webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/WSDoAllHandler.java

Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/context/MessageContext.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/context/MessageContext.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/context/MessageContext.java (original)
+++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/context/MessageContext.java Thu Nov 16 20:01:19 2006
@@ -29,6 +29,7 @@
 import org.apache.axis2.client.Options;
 import org.apache.axis2.description.*;
 import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.engine.Handler;
 import org.apache.neethi.Policy;
 
 import javax.activation.DataHandler;
@@ -36,6 +37,8 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Map;
 
 /**
@@ -140,6 +143,9 @@
      */
     private ArrayList executionChain = new ArrayList();
 
+    private LinkedList inboundExecutedPhases = new LinkedList();
+    private LinkedList outboundExecutedPhases = new LinkedList();
+
     // Are we doing REST now?
     private boolean doingREST;
 
@@ -259,7 +265,91 @@
     public ArrayList getExecutionChain() {
         return executionChain;
     }
+    
+    /**
+     * Add a Phase to the collection of executed phases for the inbound path.
+     * Phases will be inserted in a LIFO data structure.
+     * @param phase The phase to add to the list.
+     */
+    public void addInboundExecutedPhase(Handler phase)
+    {
+      inboundExecutedPhases.addFirst(phase); 
+    }
+        
+    /**
+     * Remove the first Phase in the collection of executed phases for the
+     * inbound path.
+     */
+    public void removeFirstInboundExecutedPhase()
+    {
+      if (inboundExecutedPhases != null)
+      {
+        inboundExecutedPhases.removeFirst();
+      }
+    }
+
+    /**
+     * Get an iterator over the inbound executed phase list.
+     * @return An Iterator over the LIFO data structure.
+     */
+    public Iterator getInboundExecutedPhases()
+    {
+      return inboundExecutedPhases.iterator();
+    }
+          
+    /**
+     * Reset the list of executed inbound phases.
+     * This is needed because the OutInAxisOperation currently invokes
+     * receive() even when a fault occurs, and we will have already executed
+     * the flowComplete on those before receiveFault() is called.
+     */
+    public void resetInboundExecutedPhases()
+    {
+      inboundExecutedPhases = new LinkedList();
+    }
+        
+    /**
+     * Add a Phase to the collection of executed phases for the outbound path.
+     * Phases will be inserted in a LIFO data structure.
+     * @param phase The phase to add to the list.
+     */
+    public void addOutboundExecutedPhase(Handler phase)
+    {
+      outboundExecutedPhases.addFirst(phase); 
+    }
+        
+    /**
+     * Remove the first Phase in the collection of executed phases for the
+     * outbound path.
+     */
+    public void removeFirstOutboundExecutedPhase()
+    {
+      if (outboundExecutedPhases != null)
+      {
+        outboundExecutedPhases.removeFirst();
+      }
+    }
 
+    /**
+     * Get an iterator over the outbound executed phase list.
+     * @return An Iterator over the LIFO data structure.
+     */
+    public Iterator getOutboundExecutedPhases()
+    {
+      return outboundExecutedPhases.iterator();
+    }
+        
+    /**
+     * Reset the list of executed outbound phases.
+     * This is needed because the OutInAxisOperation currently invokes
+     * receive() even when a fault occurs, and we will have already executed
+     * the flowComplete on those before receiveFault() is called.
+     */
+    public void resetOutboundExecutedPhases()
+    {
+      outboundExecutedPhases = new LinkedList();
+    }
+    
     /**
      * @return Returns EndpointReference.
      */

Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisEngine.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisEngine.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisEngine.java (original)
+++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisEngine.java Thu Nov 16 20:01:19 2006
@@ -20,12 +20,14 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
+import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.soap.SOAP11Constants;
 import org.apache.axiom.soap.SOAP12Constants;
 import org.apache.axiom.soap.SOAPConstants;
 import org.apache.axiom.soap.SOAPEnvelope;
 import org.apache.axiom.soap.SOAPHeaderBlock;
 import org.apache.axis2.AxisFault;
+import org.apache.axis2.client.async.Callback;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.context.OperationContext;
@@ -34,6 +36,7 @@
 import org.apache.axis2.engine.Handler.InvocationResponse;
 import org.apache.axis2.i18n.Messages;
 import org.apache.axis2.transport.TransportSender;
+import org.apache.axis2.util.CallbackReceiver;
 import org.apache.axis2.util.MessageContextBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -50,6 +53,11 @@
     private static final Log log = LogFactory.getLog(AxisEngine.class);
     private ConfigurationContext engineContext;
 
+    private static boolean RESUMING_EXECUTION = true;
+    private static boolean NOT_RESUMING_EXECUTION = false;
+    private static boolean IS_INBOUND = true;
+    private static boolean IS_OUTBOUND = false;
+        
     /**
      * Constructor AxisEngine
      */
@@ -125,7 +133,7 @@
             throws AxisFault {
         return MessageContextBuilder.createFaultMessageContext(processingContext, e);
     }
-
+   
     /**
      * This methods represents the inflow of the Axis, this could be either at the server side or the client side.
      * Here the <code>ExecutionChain</code> is created using the Phases. The Handlers at the each Phases is ordered in
@@ -145,18 +153,43 @@
         // affecting later messages.
         msgContext.setExecutionChain((ArrayList) preCalculatedPhases.clone());
         msgContext.setFLOW(MessageContext.IN_FLOW);
-        InvocationResponse pi = invoke(msgContext);
-
-        if (pi.equals(InvocationResponse.CONTINUE)) {
-            if (msgContext.isServerSide()) {
-
-                // invoke the Message Receivers
-                checkMustUnderstand(msgContext);
+        try
+        {
+          InvocationResponse pi = invoke(msgContext, IS_INBOUND, NOT_RESUMING_EXECUTION);
+
+          if (pi.equals(InvocationResponse.CONTINUE))
+          {
+            if (msgContext.isServerSide())
+            {
+              // invoke the Message Receivers
+              checkMustUnderstand(msgContext);
+              
+              MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
 
-                MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
-
-                receiver.receive(msgContext);
+              receiver.receive(msgContext);
             }
+            flowComplete(msgContext, true);
+          }
+          else if (pi.equals(InvocationResponse.SUSPEND))
+          {
+            return;
+          }
+          else if (pi.equals(InvocationResponse.ABORT))
+          {
+            flowComplete(msgContext, true);
+            return;
+          }
+          else
+          {
+            String errorMsg = "Unrecognized InvocationResponse encountered in AxisEngine.receive()";
+            log.error(errorMsg);
+            throw new AxisFault(errorMsg);
+          }
+        }
+        catch (AxisFault e)
+        {
+          flowComplete(msgContext, true);
+          throw e;
         }
     }
 
@@ -166,32 +199,104 @@
      * if the msgContext is pauesd then the execution will be breaked
      *
      * @param msgContext
-     * @return An InvocationResponse that indicates what
+     * @return An InvocationResponse that indicates what 
      *         the next step in the message processing should be.
      * @throws AxisFault
      */
-    public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
+    public InvocationResponse invoke(MessageContext msgContext, boolean inbound, boolean resuming) throws AxisFault {
         if (msgContext.getCurrentHandlerIndex() == -1) {
             msgContext.setCurrentHandlerIndex(0);
         }
 
         InvocationResponse pi = InvocationResponse.CONTINUE;
-
+        
         while (msgContext.getCurrentHandlerIndex() < msgContext.getExecutionChain().size()) {
             Handler currentHandler = (Handler) msgContext.getExecutionChain().
                     get(msgContext.getCurrentHandlerIndex());
-            pi = currentHandler.invoke(msgContext);
+                        
+            try
+            {
+              if (!resuming)
+              {
+                if (inbound)
+                {
+                  msgContext.addInboundExecutedPhase(currentHandler);
+                }
+                else
+                {
+                  msgContext.addOutboundExecutedPhase(currentHandler);
+                }
+              }
+              else
+              {
+                /* If we are resuming the flow, we don't want to add the phase 
+                 * again, as it has already been added.
+                 */
+                resuming = false;
+              }
+              pi = currentHandler.invoke(msgContext);
+            }
+            catch (AxisFault e)
+            {
+              if (msgContext.getCurrentPhaseIndex() == 0)
+              {
+                /* If we got a fault, we still want to add the phase to the
+                 list to be executed for flowComplete(...) unless this was
+                 the first handler, as then the currentPhaseIndex will be
+                 set to 0 and this will look like we've executed all of the
+                 handlers.  If, at some point, a phase really needs to get
+                 notification of flowComplete, then we'll need to introduce
+                 some more complex logic to keep track of what has been
+                 executed.*/ 
+                if (inbound)
+                {
+                  msgContext.removeFirstInboundExecutedPhase();
+                }
+                else
+                {
+                  msgContext.removeFirstOutboundExecutedPhase();
+                }
+              }
+              throw e;
+            }
 
             if (pi.equals(InvocationResponse.SUSPEND) ||
-                    pi.equals(InvocationResponse.ABORT)) {
-                break;
+                pi.equals(InvocationResponse.ABORT))
+            {
+              break;
             }
+
             msgContext.setCurrentHandlerIndex(msgContext.getCurrentHandlerIndex() + 1);
         }
-
+        
         return pi;
     }
 
+    private void flowComplete(MessageContext msgContext, boolean inbound) 
+    {
+      Iterator invokedPhaseIterator = inbound?msgContext.getInboundExecutedPhases():msgContext.getOutboundExecutedPhases(); 
+      
+      Handler currentHandler;
+      while (invokedPhaseIterator.hasNext())
+      {
+        currentHandler = ((Handler)invokedPhaseIterator.next());
+        currentHandler.flowComplete(msgContext);
+      }
+          
+      /*This is needed because the OutInAxisOperation currently invokes
+       * receive() even when a fault occurs, and we will have already executed
+       * the flowComplete on those before receiveFault() is called.
+       */
+      if (inbound)
+      {
+        msgContext.resetInboundExecutedPhases();
+      }
+      else
+      {
+        msgContext.resetOutboundExecutedPhases();
+      }
+    }
+
     /**
      * If the msgConetext is puased and try to invoke then
      * first invoke the phase list and after the message receiver
@@ -202,18 +307,28 @@
      * @throws AxisFault
      */
     public InvocationResponse resumeReceive(MessageContext msgContext) throws AxisFault {
+      //REVIEW: This name is a little misleading, as it seems to indicate that there should be a resumeReceiveFault as well, when, in fact, this does both 
+      //REVIEW: Unlike with receive, there is no wrapping try/catch clause which would
+      //fire off the flowComplete on an error, as we have to assume that the
+      //message will be resumed again, but perhaps we need to unwind back to
+      //the point at which the message was resumed and provide another API
+      //to allow the full unwind if the message is going to be discarded.
         //invoke the phases
-        InvocationResponse pi = invoke(msgContext);
-
-        if (pi.equals(InvocationResponse.CONTINUE)) {
-            //invoking the MR
-            if (msgContext.isServerSide()) {
-                // invoke the Message Receivers
-                checkMustUnderstand(msgContext);
-                MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
-                receiver.receive(msgContext);
-            }
+        InvocationResponse pi = invoke(msgContext, IS_INBOUND, RESUMING_EXECUTION);
+        //invoking the MR
+        
+        if (pi.equals(InvocationResponse.CONTINUE))
+        {
+          if (msgContext.isServerSide())
+          {
+            // invoke the Message Receivers
+            checkMustUnderstand(msgContext);
+            MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
+            receiver.receive(msgContext);
+          }
+          flowComplete(msgContext, true);
         }
+        
         return pi;
     }
 
@@ -224,18 +339,27 @@
      * @param msgContext
      * @return An InvocationResponse allowing the invoker to perhaps determine
      *         whether or not the message processing will ever succeed.
+     * @throws AxisFault
      */
     public InvocationResponse resumeSend(MessageContext msgContext) throws AxisFault {
+      //REVIEW: This name is a little misleading, as it seems to indicate that there should be a resumeSendFault as well, when, in fact, this does both 
+      //REVIEW: Unlike with send, there is no wrapping try/catch clause which would
+      //fire off the flowComplete on an error, as we have to assume that the
+      //message will be resumed again, but perhaps we need to unwind back to
+      //the point at which the message was resumed and provide another API
+      //to allow the full unwind if the message is going to be discarded.
         //invoke the phases
-        InvocationResponse pi = invoke(msgContext);
-        //Invoking Tarnsport Sender
-        if (pi.equals(InvocationResponse.CONTINUE)) {
+        InvocationResponse pi = invoke(msgContext, IS_OUTBOUND, RESUMING_EXECUTION);
+        //Invoking Transport Sender
+        if (pi.equals(InvocationResponse.CONTINUE))
+        {
             // write the Message to the Wire
             TransportOutDescription transportOut = msgContext.getTransportOut();
             TransportSender sender = transportOut.getSender();
             sender.invoke(msgContext);
+            flowComplete(msgContext, false);
         }
-
+        
         return pi;
     }
 
@@ -248,7 +372,7 @@
      */
     public void receiveFault(MessageContext msgContext) throws AxisFault {
 
-        log.debug(Messages.getMessage("receivederrormessage",
+    	log.debug(Messages.getMessage("receivederrormessage",
                 msgContext.getMessageID()));
         ConfigurationContext confContext = msgContext.getConfigurationContext();
         ArrayList preCalculatedPhases =
@@ -258,24 +382,49 @@
         // affecting later messages.
         msgContext.setExecutionChain((ArrayList) preCalculatedPhases.clone());
         msgContext.setFLOW(MessageContext.IN_FAULT_FLOW);
-        InvocationResponse pi = invoke(msgContext);
-
-        if (pi.equals(InvocationResponse.CONTINUE)) {
-            if (msgContext.isServerSide()) {
-
-                // invoke the Message Receivers
-                checkMustUnderstand(msgContext);
+        
+        try
+        {
+          InvocationResponse pi = invoke(msgContext, IS_INBOUND, NOT_RESUMING_EXECUTION);
+
+          if (pi.equals(InvocationResponse.CONTINUE))
+          {
+            if (msgContext.isServerSide())
+            {
+              // invoke the Message Receivers
+              checkMustUnderstand(msgContext);
+              
+              MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
 
-                MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
-
-                receiver.receive(msgContext);
+              receiver.receive(msgContext);
             }
+            flowComplete(msgContext, true);
+          }
+          else if (pi.equals(InvocationResponse.SUSPEND))
+          {
+            return;
+          }
+          else if (pi.equals(InvocationResponse.ABORT))
+          {
+            flowComplete(msgContext, true);
+            return;
+          }
+          else
+          {
+            String errorMsg = "Unrecognized InvocationResponse encountered in AxisEngine.receiveFault()";
+            log.error(errorMsg);
+            throw new AxisFault(errorMsg);
+          }
+        }
+        catch (AxisFault e)
+        {
+          flowComplete(msgContext, true);
+          throw e;
         }
     }
 
     /**
      * Resume processing of a message.
-     *
      * @param msgctx
      * @return An InvocationResponse allowing the invoker to perhaps determine
      *         whether or not the message processing will ever succeed.
@@ -313,13 +462,15 @@
                 .getAxisConfiguration().getGlobalOutPhases().clone());
         msgContext.setExecutionChain(outPhases);
         msgContext.setFLOW(MessageContext.OUT_FLOW);
-        InvocationResponse pi = invoke(msgContext);
-
-        if (pi.equals(InvocationResponse.CONTINUE)) {
+        try
+        {
+          InvocationResponse pi = invoke(msgContext, IS_OUTBOUND, NOT_RESUMING_EXECUTION);
 
+          if (pi.equals(InvocationResponse.CONTINUE))
+          {
             // write the Message to the Wire
             TransportOutDescription transportOut = msgContext.getTransportOut();
-            if (transportOut == null) {
+            if(transportOut == null) {
                 throw new AxisFault("Transport out has not been set");
             }
             TransportSender sender = transportOut.getSender();
@@ -334,6 +485,29 @@
             } else {
                 sender.invoke(msgContext);
             }
+            //REVIEW: In the case of the TransportNonBlockingInvocationWorker, does this need to wait until that finishes?
+            flowComplete(msgContext, false);
+          }
+          else if (pi.equals(InvocationResponse.SUSPEND))
+          {
+            return;
+          }
+          else if (pi.equals(InvocationResponse.ABORT))
+          {
+            flowComplete(msgContext, false);
+            return;
+          }
+          else
+          {
+            String errorMsg = "Unrecognized InvocationResponse encountered in AxisEngine.send()";
+            log.error(errorMsg);
+            throw new AxisFault(errorMsg);
+          }
+        }
+        catch (AxisFault e)
+        {
+          flowComplete(msgContext, false);          
+          throw e;
         }
     }
 
@@ -346,34 +520,75 @@
     public void sendFault(MessageContext msgContext) throws AxisFault {
         OperationContext opContext = msgContext.getOperationContext();
 
-        InvocationResponse pi = InvocationResponse.CONTINUE;
-
+        //FIXME: If this gets paused in the operation-specific phases, the resume is not going to function correctly as the phases will not have all been set 
+        
         // find and execute the Fault Out Flow Handlers
         if (opContext != null) {
             AxisOperation axisOperation = opContext.getAxisOperation();
             ArrayList faultExecutionChain = axisOperation.getPhasesOutFaultFlow();
 
             //adding both operation specific and global out fault flows.
-
+            
             ArrayList outFaultPhases = new ArrayList();
             outFaultPhases.addAll((ArrayList) faultExecutionChain.clone());
             msgContext.setExecutionChain((ArrayList) outFaultPhases.clone());
             msgContext.setFLOW(MessageContext.OUT_FAULT_FLOW);
-            pi = invoke(msgContext);
+            try
+            {
+              InvocationResponse pi = invoke(msgContext, IS_OUTBOUND, NOT_RESUMING_EXECUTION);
+              
+              if (pi.equals(InvocationResponse.SUSPEND))
+              {
+                log.warn("The resumption of this flow may function incorrectly, as the OutFaultFlow will not be used");
+                return;
+              }
+              else if (pi.equals(InvocationResponse.ABORT))
+              {
+                flowComplete(msgContext, false);
+                return;
+              }
+              else if (!pi.equals(InvocationResponse.CONTINUE))
+              {
+                String errorMsg = "Unrecognized InvocationResponse encountered in AxisEngine.sendFault()";
+                log.error(errorMsg);
+                throw new AxisFault(errorMsg);
+              }
+            }
+            catch (AxisFault e)
+            {
+              flowComplete(msgContext, false);
+              throw e;
+            }
         }
-
-        if (pi.equals(InvocationResponse.CONTINUE)) {
-            msgContext.setExecutionChain(
-                    (ArrayList) msgContext.getConfigurationContext()
-                            .getAxisConfiguration().getOutFaultFlow().clone());
-            msgContext.setFLOW(MessageContext.OUT_FAULT_FLOW);
-            invoke(msgContext);
-
-            // Actually send the SOAP Fault
-            TransportSender sender = msgContext.getTransportOut().getSender();
-
-            sender.invoke(msgContext);
+        
+        msgContext.setExecutionChain((ArrayList) msgContext.getConfigurationContext().getAxisConfiguration().getOutFaultFlow().clone());
+        msgContext.setFLOW(MessageContext.OUT_FAULT_FLOW);
+        InvocationResponse pi = invoke(msgContext, IS_OUTBOUND, NOT_RESUMING_EXECUTION);
+
+        if (pi.equals(InvocationResponse.CONTINUE))
+        {
+          // Actually send the SOAP Fault
+          TransportSender sender = msgContext.getTransportOut().getSender();
+
+          sender.invoke(msgContext);
+          flowComplete(msgContext, false);
+        }
+        else if (pi.equals(InvocationResponse.SUSPEND))
+        {
+          return;
+        }
+        else if (pi.equals(InvocationResponse.ABORT))
+        {
+          flowComplete(msgContext, false);
+          return;
+        }
+        else
+        {
+          String errorMsg = "Unrecognized InvocationResponse encountered in AxisEngine.sendFault()";
+          log.error(errorMsg);
+          throw new AxisFault(errorMsg);
         }
+        
     }
 
     /**

Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Handler.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Handler.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Handler.java (original)
+++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Handler.java Thu Nov 16 20:01:19 2006
@@ -26,6 +26,7 @@
  * Interface Handler
  */
 public interface Handler {
+
     /**
      * Since this might change the whole behavior of Axis2 handlers, and since this is still under discussion 
      * (http://marc.theaimsgroup.com/?l=axis-dev&m=114504084929285&w=2) implementation of this method is deferred.
@@ -41,22 +42,40 @@
     public void init(HandlerDescription handlerdesc);
 
     /**
-     * Invoke is called to do the actual work of the Handler object.
-     * If there is a fault during the processing of this method it is
-     * invoke's job to catch the exception and undo any partial work
-     * that has been completed.
+     * This method will be called on each registered handler when a message
+     * needs to be processed.  If the message processing is paused by the
+     * handler, then this method will be called again for the handler that
+     * paused the processing once it is resumed.
+     * 
+     * This method may be called concurrently from multiple threads.
      * 
-     * N.B. This method may be called concurrently from multiple threads.
+     * Handlers that want to determine the type of message that is to be
+     * processed (e.g. response vs request, inbound vs. outbound, etc.) can
+     * retrieve that information from the MessageContext via
+     * MessageContext.getFLOW() and
+     * MessageContext.getAxisOperation().getMessageExchangePattern() APIs.
      *
      * @param msgContext the <code>MessageContext</code> to process with this
      *                   <code>Handler</code>.
-     * @return An InvocationResponse that indicates what
+     * @return An InvocationResponse that indicates what 
      *         the next step in the message processing should be.
      * @throws AxisFault if the handler encounters an error
      */
     public InvocationResponse invoke(MessageContext msgContext) throws AxisFault;
 
     /**
+     * This method will be called on each registered handler that had its
+     * invoke(...) method called during the processing of the message, once
+     * the message processing has completed.  During execution of the
+     * flowComplete's, handlers are invoked in the opposite order that they
+     * were invoked originally.
+     * 
+     * @param msgContext the <code>MessageContext</code> to process with this
+     *                   <code>Handler</code>.
+     */
+    public void flowComplete(MessageContext msgContext);
+    
+    /**
      * Gets the HandlerDescription of a handler. This is used as an input to get phaseRule of a handler.
      *
      * @return Returns HandlerDescription.
@@ -107,5 +126,4 @@
         return instructionID;
       }
     }
-    
 }

Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Phase.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Phase.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Phase.java (original)
+++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Phase.java Thu Nov 16 20:01:19 2006
@@ -398,6 +398,42 @@
         return pi;
     }
 
+    public void flowComplete(MessageContext msgContext)
+    {
+      boolean isDebugEnabled = log.isDebugEnabled();
+      
+      if (isDebugEnabled)
+      {
+        log.debug("Invoking flowComplete() in Phase \"" + phaseName + "\"");
+      }
+      
+      /*This will be non-zero if we failed during execution of one of the
+       *handlers in this phase*/
+      int currentHandlerIndex = msgContext.getCurrentPhaseIndex();
+      if (currentHandlerIndex == 0)
+      {
+        currentHandlerIndex = handlers.size();
+      }
+      else
+      {
+        /*We need to set it to 0 so that any previous phases will execute all
+         * of their handlers.*/
+        msgContext.setCurrentPhaseIndex(0);
+      }
+      
+      for (; currentHandlerIndex > 0; currentHandlerIndex--)
+      {
+        Handler handler = (Handler) handlers.get(currentHandlerIndex-1);
+        
+        if (isDebugEnabled)
+        {
+          log.debug("Invoking flowComplete() for Handler '" + handler.getName() + "' in Phase '" + phaseName + "'");
+        }
+        
+        handler.flowComplete(msgContext);
+      }
+    }
+    
     public String toString() {
         return this.getPhaseName();
     }

Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/handlers/AbstractHandler.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/handlers/AbstractHandler.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/handlers/AbstractHandler.java (original)
+++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/handlers/AbstractHandler.java Thu Nov 16 20:01:19 2006
@@ -17,6 +17,7 @@
 
 package org.apache.axis2.handlers;
 
+import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.description.HandlerDescription;
 import org.apache.axis2.description.Parameter;
 import org.apache.axis2.engine.Handler;
@@ -99,5 +100,9 @@
      */
     public Parameter getParameter(String name) {
         return handlerDesc.getParameter(name);
+    }
+    
+    public void flowComplete(MessageContext msgContext)
+    {
     }
 }

Modified: webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartReceiver.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartReceiver.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartReceiver.java (original)
+++ webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartReceiver.java Thu Nov 16 20:01:19 2006
@@ -124,6 +124,9 @@
 
     }
 
+    public void flowComplete(MessageContext msgContext)
+    {
+    }
     
     public HandlerDescription getHandlerDesc() {
         return this.handlerDesc;

Modified: webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartSender.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartSender.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartSender.java (original)
+++ webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/RampartSender.java Thu Nov 16 20:01:19 2006
@@ -67,6 +67,10 @@
         return InvocationResponse.CONTINUE;        
     }
 
+    public void flowComplete(MessageContext msgContext)
+    {
+    }
+    
     public HandlerDescription getHandlerDesc() {
         return this.handlerDesc;
     }

Modified: webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/WSDoAllHandler.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/WSDoAllHandler.java?view=diff&rev=476044&r1=476043&r2=476044
==============================================================================
--- webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/WSDoAllHandler.java (original)
+++ webservices/axis2/trunk/java/modules/security/src/org/apache/rampart/handler/WSDoAllHandler.java Thu Nov 16 20:01:19 2006
@@ -76,6 +76,10 @@
         return InvocationResponse.CONTINUE;        
     }
 
+    public void flowComplete(MessageContext msgContext)
+    {
+    }
+    
     /**
      * Method getName.
      *



---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org