001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.systest.ws.util;
019:
020: import java.io.ByteArrayInputStream;
021: import java.util.ArrayList;
022: import java.util.List;
023:
024: import javax.xml.namespace.QName;
025: import javax.xml.parsers.DocumentBuilder;
026: import javax.xml.parsers.DocumentBuilderFactory;
027:
028: import org.w3c.dom.Document;
029: import org.w3c.dom.Element;
030: import org.w3c.dom.Node;
031:
032: import junit.framework.Assert;
033:
034: import org.apache.cxf.ws.rm.RMConstants;
035:
036: public class MessageFlow extends Assert {
037:
038: private List<byte[]> inStreams;
039: private List<byte[]> outStreams;
040: private List<Document> outboundMessages;
041: private List<Document> inboundMessages;
042:
043: public MessageFlow(List<byte[]> out, List<byte[]> in)
044: throws Exception {
045: inboundMessages = new ArrayList<Document>();
046: outboundMessages = new ArrayList<Document>();
047: reset(out, in);
048: }
049:
050: public void clear() throws Exception {
051: inStreams.clear();
052: outStreams.clear();
053: }
054:
055: public final void reset(List<byte[]> out, List<byte[]> in)
056: throws Exception {
057: for (int i = 0; i < inboundMessages.size(); i++) {
058: in.remove(0);
059: }
060: inStreams = in;
061: for (int i = 0; i < outboundMessages.size(); i++) {
062: out.remove(0);
063: }
064: outStreams = out;
065: DocumentBuilderFactory factory = DocumentBuilderFactory
066: .newInstance();
067: factory.setNamespaceAware(true);
068: DocumentBuilder parser = factory.newDocumentBuilder();
069: inboundMessages.clear();
070: for (int i = 0; i < inStreams.size(); i++) {
071: byte[] bytes = inStreams.get(i);
072: ByteArrayInputStream is = new ByteArrayInputStream(bytes);
073: Document document = parser.parse(is);
074: inboundMessages.add(document);
075: }
076: outboundMessages.clear();
077: for (int i = 0; i < outStreams.size(); i++) {
078: byte[] bytes = outStreams.get(i);
079: ByteArrayInputStream is = new ByteArrayInputStream(bytes);
080: Document document = parser.parse(is);
081: outboundMessages.add(document);
082: }
083: }
084:
085: public void verifyActions(String[] expectedActions, boolean outbound)
086: throws Exception {
087:
088: assertEquals(expectedActions.length,
089: outbound ? outboundMessages.size() : inboundMessages
090: .size());
091:
092: for (int i = 0; i < expectedActions.length; i++) {
093: String action = outbound ? getAction(outboundMessages
094: .get(i)) : getAction(inboundMessages.get(i));
095: if (null == expectedActions[i]) {
096: assertNull((outbound ? "Outbound " : "Inbound")
097: + " message " + i + " has unexpected action: "
098: + action, action);
099: } else {
100: assertEquals((outbound ? "Outbound " : "Inbound")
101: + " message " + i
102: + " does not contain expected action header"
103: + System.getProperty("line.separator"),
104: expectedActions[i], action);
105: }
106: }
107: }
108:
109: public void verifyActionsIgnoringPartialResponses(
110: String[] expectedActions) throws Exception {
111: int j = 0;
112: for (int i = 0; i < inboundMessages.size()
113: && j < expectedActions.length; i++) {
114: String action = getAction(inboundMessages.get(i));
115: if (null == action && emptyBody(inboundMessages.get(i))) {
116: continue;
117: }
118: if (null == expectedActions[j]) {
119: assertNull("Inbound message " + i
120: + " has unexpected action: " + action, action);
121: } else {
122: assertEquals("Inbound message " + i
123: + " has unexpected action: ",
124: expectedActions[j], action);
125: }
126: j++;
127: }
128: if (j < expectedActions.length) {
129: fail("Inbound messages do not contain all expected actions.");
130: }
131: }
132:
133: public boolean checkActions(String[] expectedActions,
134: boolean outbound) throws Exception {
135:
136: if (expectedActions.length != (outbound ? outboundMessages
137: .size() : inboundMessages.size())) {
138: return false;
139: }
140:
141: for (int i = 0; i < expectedActions.length; i++) {
142: String action = outbound ? getAction(outboundMessages
143: .get(i)) : getAction(inboundMessages.get(i));
144: if (null == expectedActions[i]) {
145: if (action != null) {
146: return false;
147: }
148: } else {
149: if (!expectedActions[i].equals(action)) {
150: return false;
151: }
152: }
153: }
154: return true;
155: }
156:
157: public void verifyAction(String expectedAction, int expectedCount,
158: boolean outbound, boolean exact) throws Exception {
159: int messageCount = outbound ? outboundMessages.size()
160: : inboundMessages.size();
161: int count = 0;
162: for (int i = 0; i < messageCount; i++) {
163: String action = outbound ? getAction(outboundMessages
164: .get(i)) : getAction(inboundMessages.get(i));
165: if (null == expectedAction) {
166: if (action == null) {
167: count++;
168: }
169: } else {
170: if (expectedAction.equals(action)) {
171: count++;
172: }
173: }
174: }
175: if (exact) {
176: assertEquals("unexpected count for action: "
177: + expectedAction, expectedCount, count);
178: } else {
179: assertTrue("unexpected count for action: " + expectedAction
180: + ": " + count, expectedCount <= count);
181: }
182:
183: }
184:
185: public void verifyMessageNumbers(String[] expectedMessageNumbers,
186: boolean outbound) throws Exception {
187: verifyMessageNumbers(expectedMessageNumbers, outbound, true);
188: }
189:
190: public void verifyMessageNumbers(String[] expectedMessageNumbers,
191: boolean outbound, boolean exact) throws Exception {
192:
193: int actualMessageCount = outbound ? outboundMessages.size()
194: : inboundMessages.size();
195: if (exact) {
196: assertEquals(expectedMessageNumbers.length,
197: actualMessageCount);
198: } else {
199: assertTrue(expectedMessageNumbers.length <= actualMessageCount);
200: }
201:
202: if (exact) {
203: for (int i = 0; i < expectedMessageNumbers.length; i++) {
204: Element e = outbound ? getSequence(outboundMessages
205: .get(i)) : getSequence(inboundMessages.get(i));
206: if (null == expectedMessageNumbers[i]) {
207: assertNull((outbound ? "Outbound" : "Inbound")
208: + " message " + i
209: + " contains unexpected message number ", e);
210: } else {
211: assertEquals(
212: (outbound ? "Outbound" : "Inbound")
213: + " message "
214: + i
215: + " does not contain expected message number "
216: + expectedMessageNumbers[i],
217: expectedMessageNumbers[i],
218: getMessageNumber(e));
219: }
220: }
221: } else {
222: boolean[] matches = new boolean[expectedMessageNumbers.length];
223: for (int i = 0; i < actualMessageCount; i++) {
224: String messageNumber = null;
225: Element e = outbound ? getSequence(outboundMessages
226: .get(i)) : getSequence(inboundMessages.get(i));
227: messageNumber = null == e ? null : getMessageNumber(e);
228: for (int j = 0; j < expectedMessageNumbers.length; j++) {
229: if (messageNumber == null) {
230: if (expectedMessageNumbers[j] == null
231: && !matches[j]) {
232: matches[j] = true;
233: break;
234: }
235: } else {
236: if (messageNumber
237: .equals(expectedMessageNumbers[j])
238: && !matches[j]) {
239: matches[j] = true;
240: break;
241: }
242: }
243: }
244: }
245: for (int k = 0; k < expectedMessageNumbers.length; k++) {
246: assertTrue("no match for message number: "
247: + expectedMessageNumbers[k], matches[k]);
248: }
249: }
250: }
251:
252: public void verifyLastMessage(boolean[] expectedLastMessages,
253: boolean outbound) throws Exception {
254: verifyLastMessage(expectedLastMessages, outbound, true);
255: }
256:
257: public void verifyLastMessage(boolean[] expectedLastMessages,
258: boolean outbound, boolean exact) throws Exception {
259:
260: int actualMessageCount = outbound ? outboundMessages.size()
261: : inboundMessages.size();
262: if (exact) {
263: assertEquals(expectedLastMessages.length,
264: actualMessageCount);
265: } else {
266: assertTrue(expectedLastMessages.length <= actualMessageCount);
267: }
268:
269: for (int i = 0; i < expectedLastMessages.length; i++) {
270: boolean lastMessage;
271: Element e = outbound ? getSequence(outboundMessages.get(i))
272: : getSequence(inboundMessages.get(i));
273: lastMessage = null == e ? false : getLastMessage(e);
274: assertEquals(
275: "Outbound message "
276: + i
277: + (expectedLastMessages[i] ? " does not contain expected last message element."
278: : " contains last message element."),
279: expectedLastMessages[i], lastMessage);
280:
281: }
282: }
283:
284: public void verifyAcknowledgements(boolean[] expectedAcks,
285: boolean outbound) throws Exception {
286: assertEquals(expectedAcks.length, outbound ? outboundMessages
287: .size() : inboundMessages.size());
288:
289: for (int i = 0; i < expectedAcks.length; i++) {
290: boolean ack = outbound ? (null != getAcknowledgment(outboundMessages
291: .get(i)))
292: : (null != getAcknowledgment(inboundMessages.get(i)));
293:
294: if (expectedAcks[i]) {
295: assertTrue((outbound ? "Outbound" : "Inbound")
296: + " message " + i
297: + " does not contain expected acknowledgement",
298: ack);
299: } else {
300: assertFalse((outbound ? "Outbound" : "Inbound")
301: + " message " + i
302: + " contains unexpected acknowledgement", ack);
303: }
304: }
305: }
306:
307: public void verifyAcknowledgements(int expectedAcks,
308: boolean outbound, boolean exact) throws Exception {
309:
310: int actualMessageCount = outbound ? outboundMessages.size()
311: : inboundMessages.size();
312: int ackCount = 0;
313: for (int i = 0; i < actualMessageCount; i++) {
314: boolean ack = outbound ? (null != getAcknowledgment(outboundMessages
315: .get(i)))
316: : (null != getAcknowledgment(inboundMessages.get(i)));
317: if (ack) {
318: ackCount++;
319: }
320: }
321: if (exact) {
322: assertEquals("unexpected number of acks", expectedAcks,
323: ackCount);
324: } else {
325: assertTrue("unexpected number of acks: " + ackCount,
326: expectedAcks <= ackCount);
327: }
328: }
329:
330: public void verifyAckRequestedOutbound(boolean outbound)
331: throws Exception {
332: boolean found = false;
333: List<Document> messages = outbound ? outboundMessages
334: : inboundMessages;
335: for (Document d : messages) {
336: Element se = getAckRequested(d);
337: if (se != null) {
338: found = true;
339: break;
340: }
341: }
342: assertTrue("expected AckRequested", found);
343: }
344:
345: public void verifySequenceFault(QName code, boolean outbound,
346: int index) throws Exception {
347: Document d = outbound ? outboundMessages.get(index)
348: : inboundMessages.get(index);
349: assert null != getRMHeaderElement(d, RMConstants
350: .getSequenceFaultName());
351: }
352:
353: public void verifyHeader(QName name, boolean outbound, int index)
354: throws Exception {
355: Document d = outbound ? outboundMessages.get(index)
356: : inboundMessages.get(index);
357: assertNotNull((outbound ? "Outbound" : "Inbound") + " message "
358: + index + " does not have " + name + "header.",
359: getHeaderElement(d, name.getNamespaceURI(), name
360: .getLocalPart()));
361: }
362:
363: public void verifyNoHeader(QName name, boolean outbound, int index)
364: throws Exception {
365: Document d = outbound ? outboundMessages.get(index)
366: : inboundMessages.get(index);
367: assertNull((outbound ? "Outbound" : "Inbound") + " message "
368: + index + " has " + name + "header.", getHeaderElement(
369: d, name.getNamespaceURI(), name.getLocalPart()));
370: }
371:
372: protected String getAction(Document document) throws Exception {
373: Element e = getHeaderElement(document, RMConstants
374: .getAddressingNamespace(), "Action");
375: if (null != e) {
376: return getText(e);
377: }
378: return null;
379: }
380:
381: protected Element getSequence(Document document) throws Exception {
382: return getRMHeaderElement(document, RMConstants
383: .getSequenceName());
384: }
385:
386: public String getMessageNumber(Element elem) throws Exception {
387: for (Node nd = elem.getFirstChild(); nd != null; nd = nd
388: .getNextSibling()) {
389: if (Node.ELEMENT_NODE == nd.getNodeType()
390: && "MessageNumber".equals(nd.getLocalName())) {
391: return getText(nd);
392: }
393: }
394: return null;
395: }
396:
397: private boolean getLastMessage(Element element) throws Exception {
398: for (Node nd = element.getFirstChild(); nd != null; nd = nd
399: .getNextSibling()) {
400: if (Node.ELEMENT_NODE == nd.getNodeType()
401: && "LastMessage".equals(nd.getLocalName())) {
402: return true;
403: }
404: }
405: return false;
406: }
407:
408: protected Element getAcknowledgment(Document document)
409: throws Exception {
410: return getRMHeaderElement(document, RMConstants
411: .getSequenceAckName());
412: }
413:
414: private Element getAckRequested(Document document) throws Exception {
415: return getRMHeaderElement(document, RMConstants
416: .getAckRequestedName());
417: }
418:
419: private Element getRMHeaderElement(Document document, String name)
420: throws Exception {
421: return getHeaderElement(document, RMConstants.getNamespace(),
422: name);
423: }
424:
425: private Element getHeaderElement(Document document,
426: String namespace, String localName) throws Exception {
427: Element envelopeElement = document.getDocumentElement();
428: Element headerElement = null;
429: for (Node nd = envelopeElement.getFirstChild(); nd != null; nd = nd
430: .getNextSibling()) {
431: if (Node.ELEMENT_NODE == nd.getNodeType()
432: && "Header".equals(nd.getLocalName())) {
433: headerElement = (Element) nd;
434: break;
435: }
436: }
437: if (null == headerElement) {
438: return null;
439: }
440: for (Node nd = headerElement.getFirstChild(); nd != null; nd = nd
441: .getNextSibling()) {
442: if (Node.ELEMENT_NODE != nd.getNodeType()) {
443: continue;
444: }
445: Element element = (Element) nd;
446: String ns = element.getNamespaceURI();
447: String ln = element.getLocalName();
448: if (namespace.equals(ns) && localName.equals(ln)) {
449: return element;
450: }
451: }
452: return null;
453: }
454:
455: public void verifyMessages(int nExpected, boolean outbound) {
456: verifyMessages(nExpected, outbound, true);
457: }
458:
459: public void verifyMessages(int nExpected, boolean outbound,
460: boolean exact) {
461: if (outbound) {
462: if (exact) {
463: assertEquals("Unexpected number of outbound messages"
464: + outboundDump(), nExpected, outboundMessages
465: .size());
466: } else {
467: assertTrue("Unexpected number of outbound messages: "
468: + outboundDump(), nExpected <= outboundMessages
469: .size());
470: }
471: } else {
472: if (exact) {
473: assertEquals("Unexpected number of inbound messages",
474: nExpected, inboundMessages.size());
475: } else {
476: assertTrue("Unexpected number of inbound messages: "
477: + inboundMessages.size(),
478: nExpected <= inboundMessages.size());
479: }
480: }
481: }
482:
483: public void purgePartialResponses() throws Exception {
484: for (int i = inboundMessages.size() - 1; i >= 0; i--) {
485: if (isPartialResponse(inboundMessages.get(i))) {
486: inboundMessages.remove(i);
487: }
488: }
489: }
490:
491: public void purge() {
492: inboundMessages.clear();
493: outboundMessages.clear();
494: inStreams.clear();
495: outStreams.clear();
496: }
497:
498: public void verifyPartialResponses(int nExpected) throws Exception {
499: verifyPartialResponses(nExpected, null);
500: }
501:
502: public void verifyPartialResponses(int nExpected,
503: boolean[] piggybackedAcks) throws Exception {
504: int npr = 0;
505: for (int i = 0; i < inboundMessages.size(); i++) {
506: if (isPartialResponse(inboundMessages.get(i))) {
507: if (piggybackedAcks != null) {
508: Element ack = getAcknowledgment(inboundMessages
509: .get(i));
510: if (piggybackedAcks[npr]) {
511: assertNotNull("Partial response " + npr
512: + " does not include acknowledgement.",
513: ack);
514: } else {
515: assertNull("Partial response " + npr
516: + " has unexpected acknowledgement.",
517: ack);
518: }
519: }
520: npr++;
521: }
522: }
523: assertEquals(
524: "Inbound messages did not contain expected number of partial responses.",
525: nExpected, npr);
526: }
527:
528: public boolean isPartialResponse(Document d) throws Exception {
529: return null == getAction(d) && emptyBody(d);
530: }
531:
532: public boolean emptyBody(Document d) throws Exception {
533: Element envelopeElement = d.getDocumentElement();
534: Element bodyElement = null;
535: for (Node nd = envelopeElement.getFirstChild(); nd != null; nd = nd
536: .getNextSibling()) {
537: if (Node.ELEMENT_NODE == nd.getNodeType()
538: && "Body".equals(nd.getLocalName())) {
539: bodyElement = (Element) nd;
540: break;
541: }
542: }
543: if (null != bodyElement && bodyElement.hasChildNodes()) {
544: return false;
545: }
546: return true;
547: }
548:
549: private String outboundDump() {
550: StringBuffer buf = new StringBuffer();
551: try {
552: buf.append(System.getProperty("line.separator"));
553: for (int i = 0; i < outStreams.size(); i++) {
554: buf.append("[");
555: buf.append(i);
556: buf.append("] : ");
557: buf.append(new String(outStreams.get(i)));
558: buf.append(System.getProperty("line.separator"));
559: }
560: } catch (Exception ex) {
561: return "";
562: }
563:
564: return buf.toString();
565: }
566:
567: private String getText(Node node) {
568: for (Node nd = node.getFirstChild(); nd != null; nd = nd
569: .getNextSibling()) {
570: if (Node.TEXT_NODE == nd.getNodeType()) {
571: return nd.getNodeValue();
572: }
573: }
574: return null;
575: }
576:
577: protected QName getNodeName(Node nd) {
578: return new QName(nd.getNamespaceURI(), nd.getLocalName());
579: }
580:
581: }
|