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