001: package org.objectweb.celtix.systest.ws.rm;
002:
003: import java.util.Iterator;
004: import java.util.Map;
005: import java.util.Set;
006:
007: import javax.xml.namespace.QName;
008: import javax.xml.soap.Name;
009: import javax.xml.soap.Node;
010: import javax.xml.soap.SOAPException;
011: import javax.xml.soap.SOAPHeader;
012: import javax.xml.soap.SOAPHeaderElement;
013: import javax.xml.ws.handler.MessageContext;
014: import javax.xml.ws.handler.soap.SOAPHandler;
015: import javax.xml.ws.handler.soap.SOAPMessageContext;
016:
017: import static javax.xml.ws.handler.MessageContext.MESSAGE_OUTBOUND_PROPERTY;
018:
019: /**
020: * Discards a protion of inbound application-level messages to simulate
021: * message loss. Note that out-of-band WS-RM protocol messages are always
022: * left intact.
023: */
024: public class MessageLossSimulator implements
025: SOAPHandler<SOAPMessageContext> {
026: protected static final String WSA_NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
027: protected static final String WSA_ACTION = "Action";
028: protected static final String WSRM_NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2005/02/rm";
029:
030: /**
031: * Discard every second message
032: */
033: private static final int LOSS_FACTOR = 2;
034: private int inboundMessageCount;
035:
036: public void init(Map<String, Object> map) {
037: }
038:
039: public Set<QName> getHeaders() {
040: return null;
041: }
042:
043: public void close(MessageContext context) {
044: }
045:
046: public void destroy() {
047: }
048:
049: public boolean handleMessage(SOAPMessageContext context) {
050: System.out.println("*** MessageLoss: handling message");
051: return continueProcessing(context);
052: }
053:
054: public boolean handleFault(SOAPMessageContext context) {
055: return true;
056: }
057:
058: /**
059: * @return true if the current message is outbound
060: */
061: protected boolean isOutbound(SOAPMessageContext context) {
062: Boolean outbound = (Boolean) context
063: .get(MESSAGE_OUTBOUND_PROPERTY);
064: return outbound != null && outbound.booleanValue();
065: }
066:
067: /**
068: * @return the WS-A Action header
069: */
070: protected String getAction(SOAPMessageContext context) {
071: String action = null;
072: try {
073: SOAPHeader header = context.getMessage().getSOAPPart()
074: .getEnvelope().getHeader();
075: Iterator headerElements = header.examineAllHeaderElements();
076: while (headerElements.hasNext()) {
077: SOAPHeaderElement headerElement = (SOAPHeaderElement) headerElements
078: .next();
079: Name headerName = headerElement.getElementName();
080: if (WSA_NAMESPACE_URI.equals(headerName.getURI())
081: && WSA_ACTION.equals(headerName.getLocalName())) {
082: Iterator children = headerElement
083: .getChildElements();
084: if (children.hasNext()) {
085: action = ((Node) children.next()).getValue();
086: }
087: }
088: }
089: } catch (SOAPException e) {
090: System.out.println("*** failed to determine WS-A Action: "
091: + e);
092: }
093: return action;
094: }
095:
096: /**
097: * @return true if the current message should not be discarded
098: */
099: private synchronized boolean continueProcessing(
100: SOAPMessageContext context) {
101: System.out.println("*** inboundMessageCount: "
102: + inboundMessageCount);
103: if (!(isOutbound(context) || isRMOutOfBand(context))
104: && ++inboundMessageCount % LOSS_FACTOR == 0
105: && inboundMessageCount <= 4) {
106: discardWSHeaders(context);
107: discardBody(context);
108: System.out
109: .println("*** Discarding current inbound message ***");
110: return false;
111: }
112: return true;
113: }
114:
115: /**
116: * @return true if this is a WS-RM out-of-band protocol message
117: */
118: protected boolean isRMOutOfBand(SOAPMessageContext context) {
119: String action = getAction(context);
120: return action != null && action.startsWith(WSRM_NAMESPACE_URI);
121: }
122:
123: /**
124: * Discard any WS-* headers from the message
125: */
126: private void discardWSHeaders(SOAPMessageContext context) {
127: try {
128: SOAPHeader header = context.getMessage().getSOAPPart()
129: .getEnvelope().getHeader();
130: Iterator headerElements = header.examineAllHeaderElements();
131: while (headerElements.hasNext()) {
132: SOAPHeaderElement headerElement = (SOAPHeaderElement) headerElements
133: .next();
134: Name headerName = headerElement.getElementName();
135: if (WSRM_NAMESPACE_URI.equals(headerName.getURI())
136: || WSRM_NAMESPACE_URI.equals(headerName
137: .getURI())) {
138: headerElement.detachNode();
139: }
140: }
141: } catch (SOAPException e) {
142: System.out.println("*** discard WS headers failed: " + e);
143: }
144: }
145:
146: /**
147: * Discard the body from the message to avoid assertion failure when
148: * unmarshaling partial response (occuring when system tests are run in
149: * fork mode 'none')
150: */
151: private void discardBody(SOAPMessageContext context) {
152: try {
153: context.getMessage().getSOAPBody().removeContents();
154: } catch (SOAPException e) {
155: System.out.println("*** discard body failed: " + e);
156: }
157: }
158: }
|