You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@axis.apache.org by sc...@apache.org on 2010/11/07 15:26:53 UTC

svn commit: r1032284 - in /axis/axis2/java/core/trunk/modules: jaxws-integration/test/org/apache/axis2/jaxws/sample/ jaxws-integration/test/org/apache/axis2/jaxws/sample/addnumbershandler/ jaxws/src/org/apache/axis2/jaxws/handler/

Author: scheu
Date: Sun Nov  7 14:26:52 2010
New Revision: 1032284

URL: http://svn.apache.org/viewvc?rev=1032284&view=rev
Log:
AXIS2-4862
Contributor:Rich Scheuerle
Summary:
Ensure that if a handler changes the attachments or SOAPPart, that the JAX-WS runtime's message is updated.

Modified:
    axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/AddNumbersHandlerTests.java
    axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/addnumbershandler/AddNumbersClientProtocolHandler.java
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerResolverImpl.java
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/SoapMessageContext.java

Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/AddNumbersHandlerTests.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/AddNumbersHandlerTests.java?rev=1032284&r1=1032283&r2=1032284&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/AddNumbersHandlerTests.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/AddNumbersHandlerTests.java Sun Nov  7 14:26:52 2010
@@ -841,6 +841,53 @@ public class AddNumbersHandlerTests exte
         TestLogger.logger.debug("----------------------------------");
     }
 
+    public void testAddNumbersClientHandlerWithFalse() throws Exception {
+        AddNumbersClientLogicalHandler2 clh = new AddNumbersClientLogicalHandler2();
+        AddNumbersClientProtocolHandler  cph = new AddNumbersClientProtocolHandler();
+        cph.setPivot(true);
+        try{
+            TestLogger.logger.debug("----------------------------------");
+            TestLogger.logger.debug("test: " + getName());
+            
+            AddNumbersHandlerService service = new AddNumbersHandlerService();
+            AddNumbersHandlerPortType proxy = service.getAddNumbersHandlerPort();
+            
+            BindingProvider p = (BindingProvider)proxy;
+            
+            p.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
+                    axisEndpoint);
+
+            List<Handler> handlers = p.getBinding().getHandlerChain();
+            if (handlers == null) {
+                handlers = new ArrayList<Handler>();
+            }
+            handlers.add(clh);
+            handlers.add(cph);
+            
+            p.getBinding().setHandlerChain(handlers);
+
+            int total = proxy.addNumbersHandler(99,10);
+            
+            // Note that a return of 0 indicates that the new message that was added to
+            // in the client protocol handler was lost during handler processing.
+            assertTrue("Expected a pivot and -99 to be returned. But it was "+ total, total == -99);
+        } catch(Exception e) {
+           throw e;
+        } finally {
+            cph.setPivot(false);
+        }
+        
+        String log = readLogFile();
+        String expected_calls = 
+              "AddNumbersClientLogicalHandler2 HANDLE_MESSAGE_OUTBOUND\n"
+            + "AddNumbersClientProtocolHandler HANDLE_MESSAGE_OUTBOUND\n"
+            + "AddNumbersClientLogicalHandler2 HANDLE_MESSAGE_INBOUND\n"
+            + "AddNumbersClientProtocolHandler CLOSE\n"
+            + "AddNumbersClientLogicalHandler2 CLOSE\n";
+        assertEquals(expected_calls, log);
+            
+        TestLogger.logger.debug("----------------------------------");
+    }
     /**
      * test results should be the same as testAddNumbersClientHandler, except that
      * AddNumbersClientLogicalHandler2 doubles the first param on outbound.  Async, of course.

Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/addnumbershandler/AddNumbersClientProtocolHandler.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/addnumbershandler/AddNumbersClientProtocolHandler.java?rev=1032284&r1=1032283&r2=1032284&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/addnumbershandler/AddNumbersClientProtocolHandler.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/addnumbershandler/AddNumbersClientProtocolHandler.java Sun Nov  7 14:26:52 2010
@@ -19,9 +19,17 @@
 
 package org.apache.axis2.jaxws.sample.addnumbershandler;
 
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPPart;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 import javax.xml.ws.handler.MessageContext;
 import javax.xml.ws.handler.MessageContext.Scope;
 import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.util.Set;
 
 /*
@@ -33,6 +41,16 @@ import java.util.Set;
 public class AddNumbersClientProtocolHandler implements javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
 
     HandlerTracker tracker = new HandlerTracker(AddNumbersClientProtocolHandler.class.getSimpleName());
+    boolean forcePivot = false;
+    
+    private final String PIVOT_MESSAGE = 
+    "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"><SOAP-ENV:Body>"+
+    "<p:addNumbersHandlerResponse xmlns:p=\"http://org/test/addnumbershandler\">" +
+    "<p:return>-99</p:return>" +
+    "</p:addNumbersHandlerResponse>" +
+    "</SOAP-ENV:Body></SOAP-ENV:Envelope>";
+        
+    
     
     public void close(MessageContext messagecontext) {
         tracker.close();
@@ -52,24 +70,43 @@ public class AddNumbersClientProtocolHan
     public boolean handleMessage(SOAPMessageContext messagecontext) {
         Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
         tracker.handleMessage(outbound);
-        if (outbound) {
-
+        if (outbound && !forcePivot) {
             String appProp1 = "AddNumbersClientProtocolHandlerOutboundAppScopedProperty";
             messagecontext.put(appProp1, "myVal");
             messagecontext.setScope(appProp1, Scope.APPLICATION);
             
             String appProp2 = "AddNumbersClientProtocolHandlerOutboundHandlerScopedProperty";
             messagecontext.put(appProp2, "client apps can't see this");
+            return true;
         }
-        else {  // client inbound response
+        else if (!forcePivot) {  // client inbound response
             String appProp1 = "AddNumbersClientProtocolHandlerInboundAppScopedProperty";
             messagecontext.put(appProp1, "myVal");
             messagecontext.setScope(appProp1, Scope.APPLICATION);
             
             String appProp2 = "AddNumbersClientProtocolHandlerInboundHandlerScopedProperty";
             messagecontext.put(appProp2, "client apps can't see this");
+            return true;
+        } else {
+            // Change the message and reverse the chain
+            // I am changing the message at the SOAPPart level to make sure the new message "sticks"
+            InputStream is = new ByteArrayInputStream(PIVOT_MESSAGE.getBytes()); 
+            Source source = new StreamSource(is);
+        
+            SOAPMessage message = messagecontext.getMessage();
+            message.removeAllAttachments();
+            SOAPPart soapPart = message.getSOAPPart();
+            try {
+                soapPart.setContent(source);
+            } catch (SOAPException e) {
+                throw new RuntimeException(e);
+            }
+            return false;
         }
-        return true;
+        
     }
 
+    public void setPivot(boolean value) {
+        forcePivot = value;
+    }
 }

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java?rev=1032284&r1=1032283&r2=1032284&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java Sun Nov  7 14:26:52 2010
@@ -837,6 +837,12 @@ public class HandlerChainProcessor {
         saaj_called = false;
         soap_headers_adapter_called = false;
         
+        // If the handler changed the SOAPPart or Attachments, then we need
+        // that the Message gets updated
+        if (currentMC instanceof SoapMessageContext){
+            ((SoapMessageContext)currentMC).checkAndUpdate();
+        }
+        
         if (savedEx != null) {
             throw savedEx;
         }
@@ -860,6 +866,12 @@ public class HandlerChainProcessor {
         saaj_called = false;
         soap_headers_adapter_called = false;
         
+        // If the handler changed the SOAPPart or Attachments, then we need
+        // that the Message gets updated
+        if (currentMC instanceof SoapMessageContext){
+            ((SoapMessageContext)currentMC).checkAndUpdate();
+        }
+        
         if (savedEx != null) {
             throw savedEx;
         }

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerResolverImpl.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerResolverImpl.java?rev=1032284&r1=1032283&r2=1032284&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerResolverImpl.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerResolverImpl.java Sun Nov  7 14:26:52 2010
@@ -38,6 +38,7 @@ import org.apache.axis2.util.LoggingCont
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import javax.xml.namespace.QName;
 import javax.xml.ws.WebServiceException;
 import javax.xml.ws.handler.Handler;
 import javax.xml.ws.handler.LogicalHandler;
@@ -325,8 +326,9 @@ public class HandlerResolverImpl extends
             // There is no EndpointDescription that matches the portInfo specified so 
             // return the empty list of handlers since there are no ports that match
             if (log.isDebugEnabled()) {
+                QName qName = (portinfo == null) ? null : portinfo.getPortName();
                 log.debug("The PortInfo object did not match any ports; returning an empty list of handlers." 
-                        + "  PortInfo QName: " + portinfo.getPortName());
+                        + "  PortInfo QName: " + qName);
             }
             return handlers;
         }

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/SoapMessageContext.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/SoapMessageContext.java?rev=1032284&r1=1032283&r2=1032284&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/SoapMessageContext.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/SoapMessageContext.java Sun Nov  7 14:26:52 2010
@@ -30,13 +30,17 @@ import org.apache.axis2.jaxws.message.fa
 import org.apache.axis2.jaxws.message.factory.JAXBBlockFactory;
 import org.apache.axis2.jaxws.message.factory.MessageFactory;
 import org.apache.axis2.jaxws.registry.FactoryRegistry;
+import org.apache.axis2.util.JavaUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import javax.xml.bind.JAXBContext;
 import javax.xml.namespace.QName;
+import javax.xml.soap.AttachmentPart;
 import javax.xml.soap.SOAPConstants;
+import javax.xml.soap.SOAPEnvelope;
 import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPPart;
 import javax.xml.stream.XMLStreamException;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -53,10 +57,17 @@ public class SoapMessageContext extends 
         javax.xml.ws.handler.soap.SOAPMessageContext {
     private static final Log log = LogFactory.getLog(SoapMessageContext.class);
     
-    // cache the message object after transformation --- see getMessage and setMessage methods
+    // Cache the message object and SOAPMessage after transformation 
     Message cachedMessage = null;
     SOAPMessage cachedSoapMessage = null;
     
+    // Cache information about the SOAPMessage so that we can tell if it has changed
+    SOAPPart cachedSoapPart = null;
+    SOAPEnvelope cachedSoapEnvelope = null;
+    List<AttachmentPart> cachedAttachmentParts = new ArrayList<AttachmentPart>();
+    
+    
+    
     public SoapMessageContext(MessageContext messageCtx) {
         super(messageCtx);
     }
@@ -137,9 +148,142 @@ public class SoapMessageContext extends 
         if (msg != cachedMessage) {
             cachedMessage = msg;
             cachedSoapMessage = msg.getAsSOAPMessage();
+            cacheSOAPMessageInfo(cachedSoapMessage);
         } 
         return cachedSoapMessage;
     }
+    
+    /**
+     * Check the current (cached) SOAPMessage and make sure
+     * its internals are consistent with when it was created.
+     * If not, the Message is recreated.
+     */
+    public void checkAndUpdate()  {
+        if (log.isDebugEnabled()) {
+            log.debug("Start:checkAndUpdate");
+        }
+        if (cachedSoapMessage != null) {
+            
+            boolean match = checkSOAPMessageInfo(cachedSoapMessage);
+            
+            if (!match) {
+                if (log.isDebugEnabled()) {
+                    log.debug("checkAndUpdate detected a mismatch..");
+                }
+                setMessage(cachedSoapMessage);
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("End:checkAndUpdate");
+        }
+    }
+    
+    /**
+     * Updates information about the SOAPMessage so that
+     * we can determine later if it has changed
+     * @param sm SOAPMessage
+     */
+    private void cacheSOAPMessageInfo(SOAPMessage sm) {
+        cachedSoapPart = null;
+        cachedSoapEnvelope = null;
+        cachedAttachmentParts.clear();
+        try {
+            cachedSoapPart = sm.getSOAPPart();
+            if (cachedSoapPart != null) {
+                cachedSoapEnvelope = cachedSoapPart.getEnvelope();
+            }
+            if (sm.countAttachments() > 0) {
+                Iterator it = sm.getAttachments();
+                while (it != null && it.hasNext()) {
+                    AttachmentPart ap = (AttachmentPart) it.next();
+                    cachedAttachmentParts.add(ap);
+                }
+            }
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("Ignoring ", t);
+            }
+        }
+    }
+    
+    /**
+     * Checks the information in SOAPMessage sm against 
+     * the information previously cached.  If an exception occurs
+     * @param sm SOAPMessage
+     * @return true if match , (exceptions are interpeted as false)
+     */
+    private boolean checkSOAPMessageInfo(SOAPMessage sm) {
+        if (log.isDebugEnabled()) {
+            log.debug("checkSOAPMessageInfo with " + JavaUtils.getObjectIdentity(sm));
+        }
+        // Check SOAPPart and SOAPEnvelope identity
+        SOAPPart currentSoapPart = null;
+        SOAPEnvelope currentSoapEnvelope = null;
+        
+        try {
+            currentSoapPart = sm.getSOAPPart();
+            if (currentSoapPart != null) {
+                currentSoapEnvelope = cachedSoapPart.getEnvelope();
+            }
+            // Check object identity
+            if (cachedSoapPart != currentSoapPart) {
+                if (log.isDebugEnabled()) {
+                    log.debug("checkSOAPMessageInfo returns false due to: mismatched SOAPParts");
+                }
+                return false;
+            }
+            if (cachedSoapEnvelope != currentSoapEnvelope) {
+                if (log.isDebugEnabled()) {
+                    log.debug("checkSOAPMessageInfo returns false due to: mismatched SOAPEnvelopes");
+                }
+                return false;
+            }
+        } catch(Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("checkSOAPMessageInfo returns false due to: ", t);
+            }
+        }
+        
+        // Check AttachmentParts
+        try {
+            int currentNumAttachmentParts = sm.countAttachments();
+            if (currentNumAttachmentParts != cachedAttachmentParts.size()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("checkSOAPMessageInfo returns false due to: " +
+                            "current number of AttachmentParts is " + currentNumAttachmentParts + 
+                            " versus cached number is " + cachedAttachmentParts.size());
+                }
+                return false;
+            }
+            if (currentNumAttachmentParts > 0) {
+                if (log.isDebugEnabled()) {
+                    log.debug("checkSOAPMessageInfo detected " + currentNumAttachmentParts + "AttachmentParts");
+                }
+                Iterator cachedIT = cachedAttachmentParts.iterator();
+                Iterator currentIT = sm.getAttachments();
+                while (currentIT.hasNext() && cachedIT.hasNext()) {
+                    AttachmentPart currentAP = (AttachmentPart) currentIT.next();
+                    AttachmentPart cachedAP  = (AttachmentPart) cachedIT.next();
+                    if (currentAP != cachedAP) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("checkSOAPMessageInfo returns false due to: " +
+                                    "current AttachmentParts is " + JavaUtils.getObjectIdentity(currentAP) + 
+                                    " and cached is " + JavaUtils.getObjectIdentity(cachedAP));
+                        }
+                        return false;
+                    }     
+                }
+            }
+        } catch(Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("checkSOAPMessageInfo returns false due to: ", t);
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("checkSOAPMessageInfo returns true");
+        }
+        return true;
+    }
 
     public Set<String> getRoles() {
         // TODO implement better.  We should be doing smarter checking of the header,
@@ -167,16 +311,22 @@ public class SoapMessageContext extends 
         return roles;
     }
 
-    public void setMessage(SOAPMessage soapmessage) {
-        // TODO I don't like this at all.
+    public void setMessage(SOAPMessage soapMessage) {
+        if(log.isDebugEnabled()){
+            log.debug("setMessage new=" + JavaUtils.getObjectIdentity(soapMessage) + 
+                    " existing=" + JavaUtils.getObjectIdentity(cachedSoapMessage));
+        }
         try {
             Message msg =
-                    ((MessageFactory) FactoryRegistry.getFactory(MessageFactory.class)).createFrom(soapmessage);
+                    ((MessageFactory) FactoryRegistry.getFactory(MessageFactory.class)).createFrom(soapMessage);
             messageCtx.getMEPContext().setMessage(msg);
             cachedMessage = msg;
-            cachedSoapMessage = soapmessage;
+            cachedSoapMessage = soapMessage;
+            cacheSOAPMessageInfo(cachedSoapMessage);
         } catch (XMLStreamException e) {
-            // TODO log it, and throw something?
+            if(log.isDebugEnabled()){
+                log.debug("Ignoring exception " + e);
+            }
         }
     }