You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by na...@apache.org on 2006/10/10 21:17:13 UTC

svn commit: r462507 - in /webservices/axis2/trunk/java/modules: integration/test/org/apache/axis2/engine/ kernel/src/org/apache/axis2/context/ kernel/src/org/apache/axis2/engine/ kernel/src/org/apache/axis2/handlers/ security/src/org/apache/rampart/han...

Author: nagy
Date: Tue Oct 10 12:17:12 2006
New Revision: 462507

URL: http://svn.apache.org/viewvc?view=rev&rev=462507
Log:
AXIS2-1233
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. (Re-committed after objection withdrawn.)


Added:
    webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/HandlerExecutionTest.java
    webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/PausingHandlerExecutionTest.java
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

Added: webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/HandlerExecutionTest.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/HandlerExecutionTest.java?view=auto&rev=462507
==============================================================================
--- webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/HandlerExecutionTest.java (added)
+++ webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/HandlerExecutionTest.java Tue Oct 10 12:17:12 2006
@@ -0,0 +1,517 @@
+/*
+* Copyright 2006 The Apache Software Foundation.
+*
+* Licensed 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.axis2.engine;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.soap.SOAP12Constants;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.Constants;
+import org.apache.axis2.addressing.EndpointReference;
+import org.apache.axis2.client.Options;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.ConfigurationContextFactory;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.AxisOperation;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.engine.util.FaultThrowingService;
+import org.apache.axis2.engine.util.TestConstants;
+import org.apache.axis2.handlers.AbstractHandler;
+import org.apache.axis2.integration.TestingUtils;
+import org.apache.axis2.integration.UtilServer;
+import org.apache.axis2.integration.UtilServerBasedTestCase;
+import org.apache.axis2.phaseresolver.PhaseMetadata;
+import org.apache.axis2.util.Utils;
+
+import javax.xml.namespace.QName;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class HandlerExecutionTest extends UtilServerBasedTestCase implements
+    TestConstants
+{
+  private static boolean initDone = false;
+  private static ArrayList testResults;
+  private AxisService testService;
+  private AxisService testFailingService;
+  private QName failingServiceName = new QName("FaultThrowingService");
+  private QName failingOperationName = new QName("echoWithFault");
+  private static TestHandler middleGlobalInHandler;
+  private TestHandler firstOperationInHandler;
+  private TestHandler middleOperationInHandler;
+  private TestHandler middleOperationOutHandler;
+  
+  public HandlerExecutionTest()
+  {
+    super(HandlerExecutionTest.class.getName());
+  }
+
+  public HandlerExecutionTest(String testName)
+  {
+    super(testName);
+  }
+
+  public static Test suite()
+  {
+    return getTestSetup(new TestSuite(HandlerExecutionTest.class));
+  }
+
+  private void registerOperationLevelHandlers(AxisOperation operation)
+  {
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setRemainingPhasesInFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getRemainingPhasesInFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(firstOperationInHandler);
+        operationSpecificPhase.addHandler(middleOperationInHandler);
+        operationSpecificPhase.addHandler(new TestHandler("In6"));
+      }
+    }
+
+    operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setPhasesOutFlow(operationSpecificPhases);
+    phaseList = operation.getPhasesOutFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("Out1"));
+        operationSpecificPhase.addHandler(middleOperationOutHandler);
+        operationSpecificPhase.addHandler(new TestHandler("Out3"));
+      }
+    }
+    
+  }
+  
+  protected void setUp() throws Exception
+  {
+    testResults = new ArrayList();
+    if (!initDone)
+    {
+      initDone = true;
+
+      ArrayList globalInPhases = UtilServer.getConfigurationContext().getAxisConfiguration().getGlobalInFlow();
+      for (int i = 0; i < globalInPhases.size(); i++)
+      {
+        Phase globalInPhase = (Phase)globalInPhases.get(i);
+        if (PhaseMetadata.PHASE_PRE_DISPATCH.equals(globalInPhase.getPhaseName()))
+        {
+          globalInPhase.addHandler(new TestHandler("In1"));
+          middleGlobalInHandler = new TestHandler("In2");
+          globalInPhase.addHandler(middleGlobalInHandler);
+          globalInPhase.addHandler(new TestHandler("In3"));
+        }
+      }
+    }
+
+    firstOperationInHandler = new TestHandler("In4");
+    middleOperationInHandler = new TestHandler("In5");
+    middleOperationOutHandler = new TestHandler("Out2");
+
+    testService = Utils.createSimpleService(serviceName,
+                                            Echo.class.getName(),
+                                            operationName);
+    UtilServer.deployService(testService);
+    
+    registerOperationLevelHandlers(testService.getOperation(operationName));
+
+    testFailingService = Utils.createSimpleService(failingServiceName,
+                                                   FaultThrowingService.class.getName(),
+                                                   failingOperationName);
+    UtilServer.deployService(testFailingService);
+    registerOperationLevelHandlers(testFailingService.getOperation(failingOperationName));
+    
+  }
+
+  protected void tearDown() throws Exception
+  {
+    UtilServer.unDeployService(serviceName);
+    UtilServer.unDeployService(failingServiceName);
+    UtilServer.unDeployClientService();
+  }
+
+  private ServiceClient createClient() throws Exception
+  {
+    Options options = new Options();
+    options.setTo(targetEPR);
+    options.setSoapVersionURI(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
+    options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
+    
+    ConfigurationContext configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
+    
+    ServiceClient sender = new ServiceClient(configContext, null);
+    sender.setOptions(options);
+    return sender;
+  }
+  
+  private void executeClient() throws Exception
+  {
+    OMElement payload = TestingUtils.createDummyOMElement();
+    OMElement result = createClient().sendReceive(payload);
+
+    TestingUtils.campareWithCreatedOMElement(result);
+  }
+  
+  public void testSuccessfulInvocation() throws Exception
+  {
+    System.out.println("Starting testSuccessfulInvocation");
+    
+    OMElement payload = TestingUtils.createDummyOMElement();
+    ServiceClient sender = createClient();
+    
+    AxisOperation operation = sender.getAxisService().getOperation(ServiceClient.ANON_OUT_IN_OP);
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setRemainingPhasesInFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getRemainingPhasesInFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("CIn1"));
+        operationSpecificPhase.addHandler(new TestHandler("CIn2"));
+        operationSpecificPhase.addHandler(new TestHandler("CIn3"));
+      }
+    }
+
+    operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setPhasesOutFlow(operationSpecificPhases);
+    phaseList = operation.getPhasesOutFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("COut1"));
+        operationSpecificPhase.addHandler(new TestHandler("COut2"));
+        operationSpecificPhase.addHandler(new TestHandler("COut3"));
+      }
+    }
+    
+    OMElement result = sender.sendReceive(payload);
+
+    TestingUtils.campareWithCreatedOMElement(result);
+
+    List expectedExecutionState = Arrays.asList(new String[] {"COut1", "COut2", "COut3", "In1", "In2", "In3", "In4", "In5", "In6", "Out1", "Out2", "Out3", "FCOut3", "FCOut2", "FCOut1", "FCIn6", "FCIn5", "FCIn4", "FCIn3", "FCIn2", "FCIn1", "FCCOut3", "FCCOut2", "FCCOut1", "CIn1", "CIn2", "CIn3", "FCCIn3", "FCCIn2", "FCCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+  }
+  
+  public void testServersideFailureInService() throws Exception
+  {
+    System.out.println("Starting testServersideFailureInService");
+
+    OMFactory omFactory = OMAbstractFactory.getOMFactory();
+    OMElement payload = omFactory.createOMElement("EchoOMElement", null);
+    payload.setText(FaultThrowingService.THROW_FAULT_AS_AXIS_FAULT);
+
+    Options options = new Options();
+    options.setTo(new EndpointReference("http://127.0.0.1:" + (UtilServer.TESTING_PORT) + "/axis2/services/" + failingServiceName.getLocalPart() + "/" + failingOperationName.getLocalPart()));                                                                           
+    options.setSoapVersionURI(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
+    options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
+    options.setExceptionToBeThrownOnSOAPFault(false);
+
+    ConfigurationContext configContext =
+            ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
+    ServiceClient sender = new ServiceClient(configContext, null);
+    sender.setOptions(options);
+
+    AxisOperation operation = sender.getAxisService().getOperation(ServiceClient.ANON_OUT_IN_OP);
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setRemainingPhasesInFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getRemainingPhasesInFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("CIn1"));
+        operationSpecificPhase.addHandler(new TestHandler("CIn2"));
+        operationSpecificPhase.addHandler(new TestHandler("CIn3"));
+      }
+    }
+
+    operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setPhasesOutFlow(operationSpecificPhases);
+    phaseList = operation.getPhasesOutFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("COut1"));
+        operationSpecificPhase.addHandler(new TestHandler("COut2"));
+        operationSpecificPhase.addHandler(new TestHandler("COut3"));
+      }
+    }
+
+    String result = sender.sendReceive(payload).toString();
+
+    assertTrue(result.indexOf("test:TestFault") > -1);
+    assertTrue(result.indexOf("FaultReason</soapenv:Text>") > -1);
+    assertTrue(result.indexOf("This is a test Exception") > -1);
+    //This odd pattern of CIn FCCIn CIn FCCIn is caused by the InOutAxisOperation always executing the inflow phases, even if there was a fault (and then executing the infaulflow)
+    List expectedExecutionState = Arrays.asList(new String[] {"COut1", "COut2", "COut3", "In1", "In2", "In3", "In4", "In5", "In6", "FCIn6", "FCIn5", "FCIn4", "FCIn3", "FCIn2", "FCIn1", "FCCOut3", "FCCOut2", "FCCOut1", "CIn1", "CIn2", "CIn3", "FCCIn3", "FCCIn2", "FCCIn1", "CIn1", "CIn2", "CIn3", "FCCIn3", "FCCIn2", "FCCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+  }
+
+  public void testServersideHandlerFailureInInboundOperationSpecificPhase() throws Exception
+  {
+    System.out.println("Starting testServersideHandlerFailureInInboundOperationSpecificPhase");
+
+    middleOperationInHandler.shouldFail(true);
+    try
+    {
+      executeClient();
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+    List expectedExecutionState = Arrays.asList(new String[] {"In1", "In2", "In3", "In4", "kaboom", "FCIn4", "FCIn3", "FCIn2", "FCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+    middleOperationInHandler.shouldFail(false);
+  }
+  
+  public void testServersideHandlerFailureInInboundOperationSpecificPhaseWithFirstHandler() throws Exception
+  {
+    System.out.println("Starting testServersideHandlerFailureInOutboundPhaseWithFirstHandler");
+    firstOperationInHandler.shouldFail(true);
+    try
+    {
+      executeClient();
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+    List expectedExecutionState = Arrays.asList(new String[] {"In1", "In2", "In3", "kaboom", "FCIn3", "FCIn2", "FCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+    firstOperationInHandler.shouldFail(false);
+  }
+
+  public void testServersideHandlerFailureInInboundGlobalPhase() throws Exception
+  {
+    System.out.println("Starting testServersideHandlerFailureInGlobalPhase");
+    
+    middleGlobalInHandler.shouldFail(true);
+    try
+    {
+      executeClient();
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+    List expectedExecutionState = Arrays.asList(new String[] {"In1", "kaboom", "FCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+    middleGlobalInHandler.shouldFail(false);
+  }
+  
+  public void testServersideHandlerFailureInOutboundPhase() throws Exception
+  {
+    System.out.println("Starting testServersideHandlerFailureInOutboundPhase");
+    
+    middleOperationOutHandler.shouldFail(true);
+    try
+    {
+      executeClient();
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+    List expectedExecutionState = Arrays.asList(new String[] {"In1", "In2", "In3", "In4", "In5", "In6", "Out1", "kaboom", "FCOut1", "FCIn6", "FCIn5", "FCIn4", "FCIn3", "FCIn2", "FCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+    middleOperationOutHandler.shouldFail(false);
+  }
+  
+  public void testClientsideHandlerFailureInOutboundPhaseWithFirstHandler() throws Exception
+  {
+    System.out.println("Starting testClientsideHandlerFailureInOutboundPhaseWithFirstHandler");
+
+    OMElement payload = TestingUtils.createDummyOMElement();
+    ServiceClient sender = createClient();
+    
+    AxisOperation operation = sender.getAxisService().getOperation(ServiceClient.ANON_OUT_IN_OP);
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setPhasesOutFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getPhasesOutFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        //phase1.addHandler(new TestHandler("COut1"));
+        TestHandler clientOutboundHandler = new TestHandler("COut1");
+        clientOutboundHandler.shouldFail(true);
+        operationSpecificPhase.addHandler(clientOutboundHandler);
+        //phase1.addHandler(clientOutboundHandler);
+      }
+    }
+    
+    try
+    {
+      OMElement result = sender.sendReceive(payload);
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+    List expectedExecutionState = Arrays.asList(new String[] {"kaboom"});
+    assertEquals(expectedExecutionState, testResults);
+  }
+  
+  public void testClientsideHandlerFailureInOutboundPhase() throws Exception
+  {
+    System.out.println("Starting testClientsideHandlerFailureInOutboundPhase");
+
+    OMElement payload = TestingUtils.createDummyOMElement();
+    ServiceClient sender = createClient();
+    
+    AxisOperation operation = sender.getAxisService().getOperation(ServiceClient.ANON_OUT_IN_OP);
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setPhasesOutFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getPhasesOutFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("COut1"));
+        TestHandler clientOutboundHandler = new TestHandler("COut2");
+        clientOutboundHandler.shouldFail(true);
+        operationSpecificPhase.addHandler(clientOutboundHandler);
+        operationSpecificPhase.addHandler(new TestHandler("COut3"));
+      }
+    }
+    
+    try
+    {
+      OMElement result = sender.sendReceive(payload);
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+    List expectedExecutionState = Arrays.asList(new String[] {"COut1", "kaboom", "FCCOut1"});
+    assertEquals(expectedExecutionState, testResults);
+    
+  }
+
+  public void testClientsideHandlerFailureInInboundOperationSpecificPhase() throws Exception
+  {
+    System.out.println("Starting testClientsideHandlerFailureInInboundOperationSpecific");
+
+    OMElement payload = TestingUtils.createDummyOMElement();
+    ServiceClient sender = createClient();
+    
+    AxisOperation operation = sender.getAxisService().getOperation(ServiceClient.ANON_OUT_IN_OP);
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setRemainingPhasesInFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getRemainingPhasesInFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("CIn1"));
+        TestHandler clientOutboundHandler = new TestHandler("CIn2");
+        clientOutboundHandler.shouldFail(true);
+        operationSpecificPhase.addHandler(clientOutboundHandler);
+        operationSpecificPhase.addHandler(new TestHandler("CIn3"));
+      }
+    }
+    
+    try
+    {
+      OMElement result = sender.sendReceive(payload);
+      fail("An expected handler failure did not occur");
+    }
+    catch (AxisFault e)
+    {
+    }
+
+    List expectedExecutionState = Arrays.asList(new String[] {"In1", "In2", "In3", "In4", "In5", "In6", "Out1", "Out2", "Out3", "FCOut3", "FCOut2", "FCOut1", "FCIn6", "FCIn5", "FCIn4", "FCIn3", "FCIn2", "FCIn1", "CIn1", "kaboom", "FCCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+  }
+
+  private class TestHandler extends AbstractHandler
+  {
+    private String handlerName;
+    private boolean shouldFail;
+    private boolean shouldPause;
+    
+    public TestHandler(String handlerName)
+    {
+      this.handlerName = handlerName;
+    }
+    
+    public void shouldFail(boolean fail)
+    {
+      this.shouldFail = fail;
+    }
+    
+    public void shouldPause(boolean pause)
+    {
+      this.shouldPause = pause;
+    }
+    
+    public void invoke(MessageContext msgContext) throws AxisFault
+    {
+      System.out.println("TestHandler "+handlerName+" invoked");
+      if (shouldFail)
+      {
+        testResults.add("kaboom");
+        System.out.println("Handler went kaboom");
+        throw new AxisFault("Handler failed");
+      }
+      testResults.add(handlerName);
+    }
+    
+    public void flowComplete(MessageContext msgContext)
+    {
+      System.out.println("TestHandler "+handlerName+" called for flowComplete()");
+      testResults.add("FC"+handlerName);
+    }
+  }
+}

Added: webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/PausingHandlerExecutionTest.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/PausingHandlerExecutionTest.java?view=auto&rev=462507
==============================================================================
--- webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/PausingHandlerExecutionTest.java (added)
+++ webservices/axis2/trunk/java/modules/integration/test/org/apache/axis2/engine/PausingHandlerExecutionTest.java Tue Oct 10 12:17:12 2006
@@ -0,0 +1,253 @@
+/*
+* Copyright 2006 The Apache Software Foundation.
+*
+* Licensed 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.axis2.engine;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.soap.SOAP12Constants;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.Constants;
+import org.apache.axis2.client.Options;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.AxisOperation;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.engine.util.TestConstants;
+import org.apache.axis2.handlers.AbstractHandler;
+import org.apache.axis2.integration.TestingUtils;
+import org.apache.axis2.integration.UtilServer;
+import org.apache.axis2.integration.UtilServerBasedTestCase;
+import org.apache.axis2.phaseresolver.PhaseMetadata;
+import org.apache.axis2.util.Utils;
+
+import javax.xml.namespace.QName;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class PausingHandlerExecutionTest extends UtilServerBasedTestCase implements TestConstants
+{
+  private static boolean initDone = false;
+  private static ArrayList testResults;
+  private AxisService testService;
+  private static TestHandler middleGlobalInHandler;
+  private TestHandler firstOperationInHandler;
+  private TestHandler middleOperationInHandler;
+  private TestHandler middleOperationOutHandler;
+
+  public PausingHandlerExecutionTest()
+  {
+    super(PausingHandlerExecutionTest.class.getName());
+  }
+
+  public PausingHandlerExecutionTest(String testName)
+  {
+    super(testName);
+  }
+
+  public static Test suite()
+  {
+    return getTestSetup(new TestSuite(PausingHandlerExecutionTest.class));
+  }
+
+  protected void setUp() throws Exception
+  {
+    testResults = new ArrayList();
+
+    if (!initDone)
+    {
+      initDone = true;
+      ArrayList globalInPhases = UtilServer.getConfigurationContext().getAxisConfiguration().getGlobalInFlow();
+      for (int i = 0; i < globalInPhases.size(); i++)
+      {
+        Phase globalInPhase = (Phase)globalInPhases.get(i);
+        if (PhaseMetadata.PHASE_PRE_DISPATCH.equals(globalInPhase.getPhaseName()))
+        {
+          globalInPhase.addHandler(new TestHandler("In1"));
+          middleGlobalInHandler = new TestHandler("In2");
+          globalInPhase.addHandler(middleGlobalInHandler);
+          globalInPhase.addHandler(new TestHandler("In3"));
+        }
+      }
+    }
+    
+    testService = Utils.createSimpleService(serviceName, Echo.class.getName(),
+                                            operationName);
+    UtilServer.deployService(testService);
+    AxisOperation operation = testService.getOperation(operationName);
+
+    ArrayList operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(
+                                          PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setRemainingPhasesInFlow(operationSpecificPhases);
+    ArrayList phaseList = operation.getRemainingPhasesInFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        firstOperationInHandler = new TestHandler("In4");
+        operationSpecificPhase.addHandler(firstOperationInHandler);
+        middleOperationInHandler = new TestHandler("In5");
+        operationSpecificPhase.addHandler(middleOperationInHandler);
+        operationSpecificPhase.addHandler(new TestHandler("In6"));
+      }
+    }
+
+    operationSpecificPhases = new ArrayList();
+    operationSpecificPhases.add(new Phase(
+                                          PhaseMetadata.PHASE_POLICY_DETERMINATION));
+    operation.setPhasesOutFlow(operationSpecificPhases);
+    phaseList = operation.getPhasesOutFlow();
+    for (int i = 0; i < phaseList.size(); i++)
+    {
+      Phase operationSpecificPhase = (Phase)phaseList.get(i);
+      if (PhaseMetadata.PHASE_POLICY_DETERMINATION.equals(operationSpecificPhase.getPhaseName()))
+      {
+        operationSpecificPhase.addHandler(new TestHandler("Out1"));
+        middleOperationOutHandler = new TestHandler("Out2");
+        operationSpecificPhase.addHandler(middleOperationOutHandler);
+        operationSpecificPhase.addHandler(new TestHandler("Out3"));
+      }
+    }
+  }
+
+  protected void tearDown() throws Exception
+  {
+    UtilServer.unDeployService(serviceName);
+    UtilServer.unDeployClientService();
+  }
+
+  private ServiceClient createClient() throws Exception
+  {
+    Options options = new Options();
+    options.setTo(targetEPR);
+    options.setSoapVersionURI(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
+    options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
+    options.setAction(operationName.getLocalPart());
+    options.setUseSeparateListener(true);
+    
+    ConfigurationContext configContext = UtilServer.createClientConfigurationContext();
+    
+    ServiceClient sender = new ServiceClient(configContext, null);
+    sender.setOptions(options);
+    sender.engageModule(new QName("addressing"));
+    return sender;
+  }
+
+  private void executeClient() throws Exception
+  {
+    OMElement payload = TestingUtils.createDummyOMElement();
+    OMElement result = createClient().sendReceive(payload);
+
+    TestingUtils.campareWithCreatedOMElement(result);
+  }
+
+  public void testSuccessfulInvocation() throws Exception
+  {
+    System.out.println("Starting testSuccessfulInvocation");
+    middleGlobalInHandler.shouldPause(true);
+    executeClient();
+
+    /*Since the response is going back separately, we need to give the server
+     *time to unwind the rest of the invocation.*/
+    Thread.sleep(5000);
+
+    List expectedExecutionState = Arrays.asList(new String[] {"In1", "In2", "In2", "In3", "In4", "In5", "In6", "Out1", "Out2", "Out3", "FCOut3", "FCOut2", "FCOut1", "FCIn6", "FCIn5", "FCIn4", "FCIn3", "FCIn2", "FCIn1"});
+    assertEquals(expectedExecutionState, testResults);
+  }
+  
+  private class TestHandler extends AbstractHandler
+  {
+    private String handlerName;
+    private boolean shouldFail;
+    private boolean shouldPause;
+
+    public TestHandler(String handlerName)
+    {
+      this.handlerName = handlerName;
+    }
+
+    public void shouldFail(boolean fail)
+    {
+      this.shouldFail = fail;
+    }
+
+    public void shouldPause(boolean pause)
+    {
+      System.out.println("Setting shouldPause to "+pause+" for "+handlerName);
+      this.shouldPause = pause;
+    }
+
+    public void invoke(MessageContext msgContext) throws AxisFault
+    {
+      System.out.println("TestHandler " + handlerName + " invoked");
+      if (shouldFail)
+      {
+        testResults.add("kaboom");
+        System.out.println("Handler went kaboom");
+        throw new AxisFault("Handler failed");
+      }
+      testResults.add(handlerName);
+      if (shouldPause)
+      {
+        System.out.println("Handler pausing");
+        msgContext.pause();
+        shouldPause = false;
+        new Worker(msgContext).start();
+        return;
+      }
+    }
+
+    public void flowComplete(MessageContext msgContext)
+    {
+      System.out.println("TestHandler " + handlerName
+          + " called for flowComplete()");
+      testResults.add("FC" + handlerName);
+    }
+  }
+  
+  private class Worker extends Thread
+  {
+    private MessageContext msgContext;
+    
+    public Worker(MessageContext msgContext)
+    {
+      this.msgContext = msgContext;
+    }
+    
+    public void run()
+    {
+      try
+      {
+        System.out.println("Worker thread started");
+        Thread.sleep(5000);
+        AxisEngine axisEngine = new AxisEngine(msgContext.getConfigurationContext());
+        axisEngine.resume(msgContext);
+      }
+      catch (Exception e)
+      {
+        e.printStackTrace();
+        fail("An error occurred in the worker thread");
+      }
+    }
+  }
+}

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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 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;
 
 /**
@@ -127,6 +130,9 @@
      */
     private ArrayList executionChain = new ArrayList();
 
+    private LinkedList inboundExecutedPhases = new LinkedList();
+    private LinkedList outboundExecutedPhases = new LinkedList();
+
     // Are we doing REST now?
     private boolean doingREST;
 
@@ -247,6 +253,66 @@
         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); 
+    }
+    
+    /**
+     * 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); 
+    }
+    
+    /**
+     * 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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 2006
@@ -60,6 +60,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
      */
@@ -481,16 +486,28 @@
         // affecting later messages.
         msgContext.setExecutionChain((ArrayList) preCalculatedPhases.clone());
         msgContext.setFLOW(MessageContext.IN_FLOW);
-        invoke(msgContext);
-
-        if (msgContext.isServerSide() && !msgContext.isPaused()) {
-
-            // invoke the Message Receivers
-            checkMustUnderstand(msgContext);
-
-            MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
-
-            receiver.receive(msgContext);
+        try
+        {
+          invoke(msgContext, IS_INBOUND, NOT_RESUMING_EXECUTION);
+
+          if (!msgContext.isPaused())
+          {
+            if (msgContext.isServerSide())
+            {
+              // invoke the Message Receivers
+              checkMustUnderstand(msgContext);
+              
+              MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
+
+              receiver.receive(msgContext);
+            }
+            flowComplete(msgContext, true);
+          }
+        }
+        catch (AxisFault e)
+        {
+          flowComplete(msgContext, true);
+          throw e;
         }
     }
 
@@ -502,7 +519,7 @@
      * @param msgContext
      * @throws AxisFault
      */
-    public void invoke(MessageContext msgContext) throws AxisFault {
+    public void invoke(MessageContext msgContext, boolean inbound, boolean resuming) throws AxisFault {
         if (msgContext.getCurrentHandlerIndex() == -1) {
             msgContext.setCurrentHandlerIndex(0);
         }
@@ -510,7 +527,52 @@
         while (msgContext.getCurrentHandlerIndex() < msgContext.getExecutionChain().size()) {
             Handler currentHandler = (Handler) msgContext.getExecutionChain().
                     get(msgContext.getCurrentHandlerIndex());
-            currentHandler.invoke(msgContext);
+                        
+            try
+            {
+              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.addInboundExecutedPhase(currentHandler);
+                }
+                else
+                {
+                  msgContext.addOutboundExecutedPhase(currentHandler);
+                }
+              }
+              throw e;
+            }
+              
+            if (resuming)
+            {
+              /*If we are resuming the flow, we don't want to add the phase again, as it has already
+               *been added.*/
+              resuming = false;
+            }
+            else
+            {
+              if (inbound)
+              {
+                msgContext.addInboundExecutedPhase(currentHandler);
+              }
+              else
+              {
+                msgContext.addOutboundExecutedPhase(currentHandler);
+              }
+            }
 
             if (msgContext.isPaused()) {
                 break;
@@ -519,6 +581,31 @@
         }
     }
 
+    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
@@ -528,13 +615,18 @@
      */
     public void resumeReceive(MessageContext msgContext) throws AxisFault {
         //invoke the phases
-        invoke(msgContext);
+        invoke(msgContext, IS_INBOUND, RESUMING_EXECUTION);
         //invoking the MR
-        if (msgContext.isServerSide() && !msgContext.isPaused()) {
+        if (!msgContext.isPaused())
+        {          
+          if (msgContext.isServerSide())
+          {
             // invoke the Message Receivers
             checkMustUnderstand(msgContext);
             MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
             receiver.receive(msgContext);
+          }
+          flowComplete(msgContext, true);
         }
     }
 
@@ -546,13 +638,14 @@
      */
     public void resumeSend(MessageContext msgContext) throws AxisFault {
         //invoke the phases
-        invoke(msgContext);
+        invoke(msgContext, IS_OUTBOUND, RESUMING_EXECUTION);
         //Invoking Tarnsport Sender
         if (!msgContext.isPaused()) {
             // write the Message to the Wire
             TransportOutDescription transportOut = msgContext.getTransportOut();
             TransportSender sender = transportOut.getSender();
             sender.invoke(msgContext);
+            flowComplete(msgContext, false);
         }
     }
 
@@ -575,16 +668,19 @@
         // affecting later messages.
         msgContext.setExecutionChain((ArrayList) preCalculatedPhases.clone());
         msgContext.setFLOW(MessageContext.IN_FAULT_FLOW);
-        invoke(msgContext);
+        invoke(msgContext, IS_INBOUND, NOT_RESUMING_EXECUTION);
         
-        if (msgContext.isServerSide() && !msgContext.isPaused()) {
-
+        if (!msgContext.isPaused())
+        {
+          if (msgContext.isServerSide()) {
             // invoke the Message Receivers
             checkMustUnderstand(msgContext);
 
             MessageReceiver receiver = msgContext.getAxisOperation().getMessageReceiver();
 
             receiver.receive(msgContext);
+          }
+          flowComplete(msgContext, true);
         }
     }
 
@@ -620,9 +716,11 @@
                 .getAxisConfiguration().getGlobalOutPhases().clone());
         msgContext.setExecutionChain(outPhases);
         msgContext.setFLOW(MessageContext.OUT_FLOW);
-        invoke(msgContext);
+        try
+        {
+          invoke(msgContext, IS_OUTBOUND, NOT_RESUMING_EXECUTION);
 
-        if (!msgContext.isPaused()) {
+          if (!msgContext.isPaused()) {
 
             // write the Message to the Wire
             TransportOutDescription transportOut = msgContext.getTransportOut();
@@ -641,6 +739,14 @@
             } else {
                 sender.invoke(msgContext);
             }
+            //REVIEW: In the case of the TransportNonBlockingInvocationWorker, does this need to wait until that finishes?
+            flowComplete(msgContext, false);
+          }
+        }
+        catch (AxisFault e)
+        {
+          flowComplete(msgContext, false);          
+          throw e;
         }
     }
 
@@ -664,7 +770,7 @@
             outFaultPhases.addAll((ArrayList) faultExecutionChain.clone());
             msgContext.setExecutionChain((ArrayList) outFaultPhases.clone());
             msgContext.setFLOW(MessageContext.OUT_FAULT_FLOW);
-            invoke(msgContext);
+            invoke(msgContext, IS_OUTBOUND, NOT_RESUMING_EXECUTION);
         }
 
         if (!msgContext.isPaused()) {
@@ -672,12 +778,13 @@
                     (ArrayList) msgContext.getConfigurationContext()
                             .getAxisConfiguration().getOutFaultFlow().clone());
             msgContext.setFLOW(MessageContext.OUT_FAULT_FLOW);
-            invoke(msgContext);
+            invoke(msgContext, IS_OUTBOUND, NOT_RESUMING_EXECUTION);
 
             // Actually send the SOAP Fault
             TransportSender sender = msgContext.getTransportOut().getSender();
 
             sender.invoke(msgContext);
+            flowComplete(msgContext, false);
         }
     }
 

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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 2006
@@ -42,12 +42,18 @@
     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.
      * 
-     * N.B. This method may be called concurrently from multiple threads.
+     * 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>.
@@ -55,6 +61,18 @@
      */
     public void 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.
      *

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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 2006
@@ -392,6 +392,43 @@
         checkPostConditions(msgctx);
     }
 
+    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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 2006
@@ -138,4 +138,8 @@
         return this.handlerDesc.getParameter(name);
     }
 
+    public void flowComplete(MessageContext msgContext)
+    {
+    }
+
 }

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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 2006
@@ -66,6 +66,10 @@
         }
     }
 
+    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=462507&r1=462506&r2=462507
==============================================================================
--- 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 Tue Oct 10 12:17:12 2006
@@ -75,6 +75,10 @@
         }
     }
 
+    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