dblevins    2005/04/27 22:27:20

  Modified:    modules/core/src/java/org/openejb/slsb
                        HandlerChainInterceptor.java
  Log:

  Check that the SOAPMessageContext has not been inappropriately modified.  
Also use a simple stack for tracking handlers that should be involved in 
response/fault chain.
  
  Revision  Changes    Path
  1.2       +137 -33   
openejb/modules/core/src/java/org/openejb/slsb/HandlerChainInterceptor.java
  
  Index: HandlerChainInterceptor.java
  ===================================================================
  RCS file: 
/scm/openejb/openejb/modules/core/src/java/org/openejb/slsb/HandlerChainInterceptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HandlerChainInterceptor.java      16 Apr 2005 01:07:29 -0000      1.1
  +++ HandlerChainInterceptor.java      28 Apr 2005 02:27:20 -0000      1.2
  @@ -47,14 +47,21 @@
   
   import java.util.ArrayList;
   import java.util.Collections;
  +import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
  +import java.util.Stack;
   import javax.xml.rpc.JAXRPCException;
   import javax.xml.rpc.handler.Handler;
   import javax.xml.rpc.handler.HandlerChain;
   import javax.xml.rpc.handler.HandlerInfo;
   import javax.xml.rpc.handler.MessageContext;
  +import javax.xml.rpc.handler.soap.SOAPMessageContext;
   import javax.xml.rpc.soap.SOAPFaultException;
  +import javax.xml.soap.SOAPBody;
  +import javax.xml.soap.SOAPElement;
  +import javax.xml.soap.SOAPException;
  +import javax.xml.soap.SOAPMessage;
   
   import org.apache.geronimo.core.service.Interceptor;
   import org.apache.geronimo.core.service.Invocation;
  @@ -112,17 +119,16 @@
   
       static class HandlerChainImpl extends ArrayList implements 
javax.xml.rpc.handler.HandlerChain {
           private String[] roles;
  -
  -        private int lastInvoked = -1;
  +        private Stack invokedHandlers = new Stack();
   
           public HandlerChainImpl(List handlerInfos, String[] roles) {
               this.roles = roles;
               for (int i = 0; i < handlerInfos.size(); i++) {
                   HandlerInfo handlerInfo = (HandlerInfo) handlerInfos.get(i);
                   try {
  -                    Handler handler1 = (Handler) 
handlerInfo.getHandlerClass().newInstance();
  -                    handler1.init(handlerInfo);
  -                    add(handler1);
  +                    Handler handler = (Handler) 
handlerInfo.getHandlerClass().newInstance();
  +                    handler.init(handlerInfo);
  +                    add(handler);
                   } catch (Exception e) {
                       throw new JAXRPCException("Unable to initialize handler 
class: " + handlerInfo.getHandlerClass().getName(), e);
                   }
  @@ -141,50 +147,148 @@
           }
   
           public void destroy() {
  -            for (int i = (lastInvoked != -1) ? lastInvoked : size() - 1; i 
>= 0; i--) {
  -                getHandler(i).destroy();
  +            for (Iterator iterator = invokedHandlers.iterator(); 
iterator.hasNext();) {
  +                Handler handler = (Handler) iterator.next();
  +                handler.destroy();
               }
  -            lastInvoked = -1;
  +            invokedHandlers.clear();
               clear();
           }
   
  -        public boolean handleFault(MessageContext context) {
  -            for (int i = (lastInvoked != -1) ? lastInvoked : size() - 1; i 
>= 0; i--) {
  -                if (getHandler(i).handleFault(context) == false) {
  -                    return false;
  +        public boolean handleRequest(MessageContext context) {
  +            MessageSnapshot snapshot = new MessageSnapshot(context);
  +            try {
  +                for (int i = 0; i < size(); i++) {
  +                    Handler currentHandler = (Handler) get(i);
  +                    invokedHandlers.push(currentHandler);
  +                    try {
  +                        if (currentHandler.handleRequest(context) == false) {
  +                            return false;
  +                        }
  +                    } catch (SOAPFaultException e) {
  +                        throw e;
  +                    }
  +                }
  +                return true;
  +            } finally {
  +                if (!snapshot.equals(context)) {
  +                    throw new IllegalStateException("The soap message 
operation or arguments were illegally modified by the HandlerChain");
                   }
               }
  -            return true;
           }
   
  -        public boolean handleRequest(MessageContext context) {
  -            for (int i = 0; i < size(); i++) {
  -                Handler currentHandler = getHandler(i);
  -                try {
  -                    if (currentHandler.handleRequest(context) == false) {
  -                        lastInvoked = i;
  +        public boolean handleResponse(MessageContext context) {
  +            MessageSnapshot snapshot = new MessageSnapshot(context);
  +            try {
  +                for (Iterator iterator = invokedHandlers.iterator(); 
iterator.hasNext();) {
  +                    Handler handler = (Handler) iterator.next();
  +                    if (handler.handleResponse(context) == false) {
                           return false;
                       }
  -                } catch (SOAPFaultException e) {
  -                    lastInvoked = i;
  -                    throw e;
  +                }
  +                return true;
  +            } finally {
  +                if (!snapshot.equals(context)) {
  +                    throw new IllegalStateException("The soap message 
operation or arguments were illegally modified by the HandlerChain");
                   }
               }
  -            return true;
           }
   
  -        public boolean handleResponse(MessageContext context) {
  -            for (int i = (lastInvoked != -1) ? lastInvoked : size() - 1; i 
>= 0; i--) {
  -                if (getHandler(i).handleResponse(context) == false) {
  -                    return false;
  +        public boolean handleFault(MessageContext context) {
  +            MessageSnapshot snapshot = new MessageSnapshot(context);
  +            try {
  +                for (Iterator iterator = invokedHandlers.iterator(); 
iterator.hasNext();) {
  +                    Handler handler = (Handler) iterator.next();
  +                    if (handler.handleFault(context) == false) {
  +                        return false;
  +                    }
  +                }
  +                return true;
  +            } finally {
  +                if (!snapshot.equals(context)) {
  +                    throw new IllegalStateException("The soap message 
operation or arguments were illegally modified by the HandlerChain");
  +                }
  +            }
  +        }
  +    }
  +
  +    /**
  +     * Handlers cannot:
  +     * <p/>
  +     * - re-target a request to a different component.
  +     * - change the operation
  +     * - change the message part types
  +     * - change the number of message parts.
  +     */
  +    static class MessageSnapshot {
  +        private final String operationName;
  +        private final List parameterNames;
  +
  +        public MessageSnapshot(MessageContext soapMessage) {
  +
  +            SOAPMessage message = ((SOAPMessageContext) 
soapMessage).getMessage();
  +            if (message == null || message.getSOAPPart() == null) {
  +                operationName = null;
  +                parameterNames = null;
  +            } else {
  +                SOAPBody body = getBody(message);
  +
  +                SOAPElement operation = ((SOAPElement) 
body.getChildElements().next());
  +                this.operationName = operation.getElementName().toString();
  +
  +                this.parameterNames = new ArrayList();
  +                for (Iterator i = operation.getChildElements(); 
i.hasNext();) {
  +                    SOAPElement parameter = (SOAPElement) i.next();
  +                    String element = parameter.getElementName().toString();
  +                    parameterNames.add(element);
                   }
               }
  -            return true;
           }
   
  -        private Handler getHandler(int index) {
  -            return (Handler) get(index);
  +        private SOAPBody getBody(SOAPMessage message) {
  +            try {
  +                return message.getSOAPPart().getEnvelope().getBody();
  +            } catch (SOAPException e) {
  +                throw new RuntimeException(e);
  +            }
           }
   
  +        public boolean equals(Object obj) {
  +            return (obj instanceof SOAPMessageContext) ? 
equals((SOAPMessageContext) obj) : false;
  +        }
  +
  +        private boolean equals(SOAPMessageContext soapMessage) {
  +            SOAPMessage message = soapMessage.getMessage();
  +
  +            if (operationName == null) {
  +                return message == null || message.getSOAPPart() == null;
  +            }
  +
  +            SOAPBody body = getBody(message);
  +
  +            // Handlers can't change the operation
  +            SOAPElement operation = ((SOAPElement) 
body.getChildElements().next());
  +            if 
(!this.operationName.equals(operation.getElementName().toString())) {
  +                return false;
  +            }
  +
  +            Iterator parameters = operation.getChildElements();
  +            for (Iterator i = parameterNames.iterator(); i.hasNext();) {
  +                // Handlers can't remove parameters
  +                if (!parameters.hasNext()) {
  +                    return false;
  +                }
  +
  +                String original = (String) i.next();
  +                SOAPElement parameter = (SOAPElement) parameters.next();
  +                // Handlers can't change parameter types
  +                if (parameter == null || 
!original.equals(parameter.getElementName().toString())) {
  +                    return false;
  +                }
  +            }
  +
  +            // Handlers can't add parameters
  +            return !parameters.hasNext();
  +        }
       }
  -}
  +}
  \ No newline at end of file
  
  
  

Reply via email to