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.ws.rm.soap;
019:
020: import java.io.InputStream;
021: import java.lang.reflect.Method;
022: import java.math.BigInteger;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Set;
028:
029: import javax.xml.namespace.QName;
030: import javax.xml.stream.XMLInputFactory;
031: import javax.xml.stream.XMLStreamException;
032: import javax.xml.stream.XMLStreamReader;
033:
034: import org.w3c.dom.Element; //import org.w3c.dom.NodeList;
035:
036: import org.apache.cxf.BusFactory;
037: import org.apache.cxf.binding.soap.SoapFault;
038: import org.apache.cxf.binding.soap.SoapMessage;
039: import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;
040: import org.apache.cxf.headers.Header;
041: import org.apache.cxf.message.Exchange;
042: import org.apache.cxf.message.ExchangeImpl;
043: import org.apache.cxf.message.Message;
044: import org.apache.cxf.message.MessageImpl;
045: import org.apache.cxf.message.MessageUtils;
046: import org.apache.cxf.ws.rm.AckRequestedType;
047: import org.apache.cxf.ws.rm.Identifier;
048: import org.apache.cxf.ws.rm.RMConstants;
049: import org.apache.cxf.ws.rm.RMContextUtils;
050: import org.apache.cxf.ws.rm.RMProperties;
051: import org.apache.cxf.ws.rm.RMUtils;
052: import org.apache.cxf.ws.rm.SequenceAcknowledgement;
053: import org.apache.cxf.ws.rm.SequenceFault;
054: import org.apache.cxf.ws.rm.SequenceFaultType;
055: import org.apache.cxf.ws.rm.SequenceType;
056: import org.easymock.classextension.EasyMock;
057: import org.easymock.classextension.IMocksControl;
058: import org.junit.Assert;
059: import org.junit.Before;
060: import org.junit.Test;
061:
062: public class RMSoapInterceptorTest extends Assert {
063:
064: private static final String SEQ_IDENTIFIER = "http://Business456.com/RM/ABC";
065: private static final BigInteger MSG1_MESSAGE_NUMBER = BigInteger.ONE;
066: private static final BigInteger MSG2_MESSAGE_NUMBER = BigInteger.ONE
067: .add(BigInteger.ONE);
068:
069: private IMocksControl control;
070:
071: private SequenceType s1;
072: private SequenceType s2;
073: private SequenceAcknowledgement ack1;
074: private SequenceAcknowledgement ack2;
075: private AckRequestedType ar1;
076: private AckRequestedType ar2;
077:
078: @Before
079: public void setUp() {
080: control = EasyMock.createNiceControl();
081: }
082:
083: @Test
084: public void testGetUnderstoodHeaders() throws Exception {
085: RMSoapInterceptor codec = new RMSoapInterceptor();
086: Set<QName> headers = codec.getUnderstoodHeaders();
087: assertTrue("expected Sequence header", headers
088: .contains(RMConstants.getSequenceQName()));
089: assertTrue("expected SequenceAcknowledgment header", headers
090: .contains(RMConstants.getSequenceAckQName()));
091: assertTrue("expected AckRequested header", headers
092: .contains(RMConstants.getAckRequestedQName()));
093: }
094:
095: @Test
096: public void testHandleMessage() throws NoSuchMethodException {
097: Method m = RMSoapInterceptor.class.getDeclaredMethod("mediate",
098: new Class[] { SoapMessage.class });
099: RMSoapInterceptor codec = control.createMock(
100: RMSoapInterceptor.class, new Method[] { m });
101: SoapMessage msg = control.createMock(SoapMessage.class);
102: codec.mediate(msg);
103: EasyMock.expectLastCall();
104:
105: control.replay();
106: codec.handleMessage(msg);
107: control.verify();
108: }
109:
110: @Test
111: public void testMediate() throws NoSuchMethodException {
112: Method m1 = RMSoapInterceptor.class.getDeclaredMethod("encode",
113: new Class[] { SoapMessage.class });
114: Method m2 = RMSoapInterceptor.class.getDeclaredMethod("decode",
115: new Class[] { SoapMessage.class });
116: RMSoapInterceptor codec = control.createMock(
117: RMSoapInterceptor.class, new Method[] { m1, m2 });
118:
119: SoapMessage msg = control.createMock(SoapMessage.class);
120: Exchange exchange = control.createMock(Exchange.class);
121: EasyMock.expect(msg.getExchange()).andReturn(exchange);
122: EasyMock.expect(exchange.getOutMessage()).andReturn(msg);
123: codec.encode(msg);
124: EasyMock.expectLastCall();
125:
126: control.replay();
127: codec.mediate(msg);
128: control.verify();
129:
130: control.reset();
131: EasyMock.expect(msg.getExchange()).andReturn(null);
132: codec.decode(msg);
133: EasyMock.expectLastCall();
134:
135: control.replay();
136: codec.mediate(msg);
137: control.verify();
138:
139: }
140:
141: @Test
142: public void testEncode() throws Exception {
143: RMSoapInterceptor codec = new RMSoapInterceptor();
144: setUpOutbound();
145: SoapMessage message = setupOutboundMessage();
146:
147: // no RM headers
148:
149: codec.handleMessage(message);
150: verifyHeaders(message, new String[] {});
151:
152: // one sequence header
153:
154: message = setupOutboundMessage();
155: RMProperties rmps = RMContextUtils.retrieveRMProperties(
156: message, true);
157: rmps.setSequence(s1);
158: codec.encode(message);
159: verifyHeaders(message, new String[] { RMConstants
160: .getSequenceName() });
161:
162: // one acknowledgment header
163:
164: message = setupOutboundMessage();
165: rmps = RMContextUtils.retrieveRMProperties(message, true);
166: Collection<SequenceAcknowledgement> acks = new ArrayList<SequenceAcknowledgement>();
167: acks.add(ack1);
168: rmps.setAcks(acks);
169: codec.encode(message);
170: verifyHeaders(message, new String[] { RMConstants
171: .getSequenceAckName() });
172:
173: // two acknowledgment headers
174:
175: message = setupOutboundMessage();
176: rmps = RMContextUtils.retrieveRMProperties(message, true);
177: acks.add(ack2);
178: rmps.setAcks(acks);
179: codec.encode(message);
180: verifyHeaders(message, new String[] {
181: RMConstants.getSequenceAckName(),
182: RMConstants.getSequenceAckName() });
183:
184: // one ack requested header
185:
186: message = setupOutboundMessage();
187: rmps = RMContextUtils.retrieveRMProperties(message, true);
188: Collection<AckRequestedType> requested = new ArrayList<AckRequestedType>();
189: requested.add(ar1);
190: rmps.setAcksRequested(requested);
191: codec.encode(message);
192: verifyHeaders(message, new String[] { RMConstants
193: .getAckRequestedName() });
194:
195: // two ack requested headers
196:
197: message = setupOutboundMessage();
198: rmps = RMContextUtils.retrieveRMProperties(message, true);
199: requested.add(ar2);
200: rmps.setAcksRequested(requested);
201: codec.encode(message);
202: verifyHeaders(message, new String[] {
203: RMConstants.getAckRequestedName(),
204: RMConstants.getAckRequestedName() });
205: }
206:
207: @Test
208: public void testEncodeFault() throws Exception {
209: RMSoapInterceptor codec = new RMSoapInterceptor();
210: setUpOutbound();
211: SoapMessage message = setupOutboundFaultMessage();
212:
213: // no RM headers and no fault
214:
215: codec.encode(message);
216: verifyHeaders(message, new String[] {});
217:
218: // fault is not a SoapFault
219:
220: message = setupOutboundFaultMessage();
221: assertTrue(MessageUtils.isFault(message));
222: Exception ex = new RuntimeException("");
223: message.setContent(Exception.class, ex);
224: codec.encode(message);
225: verifyHeaders(message, new String[] {});
226:
227: // fault is a SoapFault but does not have a SequenceFault cause
228:
229: message = setupOutboundFaultMessage();
230: SoapFault f = new SoapFault("REASON", RMConstants
231: .getUnknownSequenceFaultCode());
232: message.setContent(Exception.class, f);
233: codec.encode(message);
234: verifyHeaders(message, new String[] {});
235:
236: // fault is a SoapFault and has a SequenceFault cause
237:
238: message = setupOutboundFaultMessage();
239: SequenceFaultType sft = RMUtils.getWSRMFactory()
240: .createSequenceFaultType();
241: sft.setFaultCode(RMConstants.getUnknownSequenceFaultCode());
242: SequenceFault sf = new SequenceFault("REASON");
243: sf.setSequenceFault(sft);
244: Identifier sid = RMUtils.getWSRMFactory().createIdentifier();
245: sid.setValue("SID");
246: sf.setSender(true);
247: f.initCause(sf);
248: message.setContent(Exception.class, f);
249: codec.encode(message);
250: verifyHeaders(message, new String[] { RMConstants
251: .getSequenceFaultName() });
252:
253: }
254:
255: @Test
256: public void testDecodeSequence() throws XMLStreamException {
257: SoapMessage message = setUpInboundMessage("resources/Message1.xml");
258: RMSoapInterceptor codec = new RMSoapInterceptor();
259: codec.handleMessage(message);
260: RMProperties rmps = RMContextUtils.retrieveRMProperties(
261: message, false);
262: SequenceType st = rmps.getSequence();
263: assertNotNull(st);
264: assertEquals(st.getIdentifier().getValue(), SEQ_IDENTIFIER);
265: assertEquals(st.getMessageNumber(), MSG1_MESSAGE_NUMBER);
266:
267: assertNull(rmps.getAcks());
268: assertNull(rmps.getAcksRequested());
269:
270: }
271:
272: @Test
273: public void testDecodeAcknowledgements() throws XMLStreamException {
274: SoapMessage message = setUpInboundMessage("resources/Acknowledgment.xml");
275: RMSoapInterceptor codec = new RMSoapInterceptor();
276: codec.handleMessage(message);
277: RMProperties rmps = RMContextUtils.retrieveRMProperties(
278: message, false);
279: Collection<SequenceAcknowledgement> acks = rmps.getAcks();
280: assertNotNull(acks);
281: assertEquals(1, acks.size());
282: SequenceAcknowledgement ack = acks.iterator().next();
283: assertNotNull(ack);
284: assertEquals(ack.getIdentifier().getValue(), SEQ_IDENTIFIER);
285: assertEquals(2, ack.getAcknowledgementRange().size());
286: assertNull(rmps.getSequence());
287: assertNull(rmps.getAcksRequested());
288: }
289:
290: @Test
291: public void testDecodeAcksRequested() throws XMLStreamException {
292: SoapMessage message = setUpInboundMessage("resources/Retransmission.xml");
293: RMSoapInterceptor codec = new RMSoapInterceptor();
294: codec.handleMessage(message);
295: RMProperties rmps = RMContextUtils.retrieveRMProperties(
296: message, false);
297: Collection<AckRequestedType> requested = rmps
298: .getAcksRequested();
299: assertNotNull(requested);
300: assertEquals(1, requested.size());
301: AckRequestedType ar = requested.iterator().next();
302: assertNotNull(ar);
303: assertEquals(ar.getIdentifier().getValue(), SEQ_IDENTIFIER);
304:
305: SequenceType s = rmps.getSequence();
306: assertNotNull(s);
307: assertEquals(s.getIdentifier().getValue(), SEQ_IDENTIFIER);
308: assertEquals(s.getMessageNumber(), MSG2_MESSAGE_NUMBER);
309:
310: assertNull(rmps.getAcks());
311: }
312:
313: private void setUpOutbound() {
314: org.apache.cxf.ws.rm.ObjectFactory factory = new org.apache.cxf.ws.rm.ObjectFactory();
315: s1 = factory.createSequenceType();
316: Identifier sid = factory.createIdentifier();
317: sid.setValue("sequence1");
318: s1.setIdentifier(sid);
319: s1.setMessageNumber(BigInteger.ONE);
320: s2 = factory.createSequenceType();
321: sid = factory.createIdentifier();
322: sid.setValue("sequence2");
323: s2.setIdentifier(sid);
324: s2.setMessageNumber(BigInteger.TEN);
325:
326: ack1 = factory.createSequenceAcknowledgement();
327: SequenceAcknowledgement.AcknowledgementRange r = factory
328: .createSequenceAcknowledgementAcknowledgementRange();
329: r.setLower(BigInteger.ONE);
330: r.setUpper(BigInteger.ONE);
331: ack1.getAcknowledgementRange().add(r);
332: ack1.setIdentifier(s1.getIdentifier());
333:
334: ack2 = factory.createSequenceAcknowledgement();
335: r = factory.createSequenceAcknowledgementAcknowledgementRange();
336: r.setLower(BigInteger.ONE);
337: r.setUpper(BigInteger.TEN);
338: ack2.getAcknowledgementRange().add(r);
339: ack2.setIdentifier(s2.getIdentifier());
340:
341: ar1 = factory.createAckRequestedType();
342: ar1.setIdentifier(s1.getIdentifier());
343:
344: ar2 = factory.createAckRequestedType();
345: ar2.setIdentifier(s2.getIdentifier());
346: }
347:
348: private SoapMessage setupOutboundMessage() throws Exception {
349: Message message = new MessageImpl();
350: SoapMessage soapMessage = new SoapMessage(message);
351: RMProperties rmps = new RMProperties();
352: RMContextUtils.storeRMProperties(soapMessage, rmps, true);
353:
354: return soapMessage;
355: }
356:
357: private SoapMessage setupOutboundFaultMessage() throws Exception {
358: Exchange ex = new ExchangeImpl();
359: Message message = new MessageImpl();
360: SoapMessage soapMessage = new SoapMessage(message);
361: ex.setOutFaultMessage(soapMessage);
362: soapMessage.setExchange(ex);
363: return soapMessage;
364: }
365:
366: private void verifyHeaders(SoapMessage message, String... names) {
367: List<Header> header = message.getHeaders();
368:
369: // check all expected headers are present
370:
371: for (String name : names) {
372: boolean found = false;
373: // NodeList headerElements = header.getChildNodes();
374: Iterator<Header> iter = header.iterator();
375: while (iter.hasNext()) {
376: Object obj = iter.next().getObject();
377: if (obj instanceof Element) {
378: Element elem = (Element) obj;
379: String namespace = elem.getNamespaceURI();
380: String localName = elem.getLocalName();
381: if (RMConstants.getNamespace().equals(namespace)
382: && localName.equals(name)) {
383: found = true;
384: break;
385: } else if (RMConstants.getAddressingNamespace()
386: .equals(namespace)
387: && localName.equals(name)) {
388: found = true;
389: break;
390: }
391: }
392: }
393: // for (int i = 0; i < headerElements.getLength(); i++) {
394: // Element headerElement = (Element)headerElements.item(i);
395: // String namespace = headerElement.getNamespaceURI();
396: // String localName = headerElement.getLocalName();
397: // if (RMConstants.getNamespace().equals(namespace)
398: // && localName.equals(name)) {
399: // found = true;
400: // break;
401: // } else if (RMConstants.getAddressingNamespace().equals(namespace)
402: // && localName.equals(name)) {
403: // found = true;
404: // break;
405: // }
406: // }
407: assertTrue("Could not find header element " + name, found);
408: }
409:
410: // no other headers should be present
411:
412: Iterator<Header> iter1 = header.iterator();
413: while (iter1.hasNext()) {
414: Object obj = iter1.next().getObject();
415: if (obj instanceof Element) {
416: Element elem = (Element) obj;
417: String namespace = elem.getNamespaceURI();
418: String localName = elem.getLocalName();
419: assertTrue(RMConstants.getNamespace().equals(namespace)
420: || RMConstants.getAddressingNamespace().equals(
421: namespace));
422: boolean found = false;
423: for (String name : names) {
424: if (localName.equals(name)) {
425: found = true;
426: break;
427: }
428: }
429: assertTrue("Unexpected header element " + localName,
430: found);
431: }
432: }
433: // NodeList headerElements = header.getChildNodes();
434: // for (int i = 0; i < headerElements.getLength(); i++) {
435: // Element headerElement = (Element)headerElements.item(i);
436: // String namespace = headerElement.getNamespaceURI();
437: // String localName = headerElement.getLocalName();
438: // assertTrue(RMConstants.getNamespace().equals(namespace)
439: // || RMConstants.getAddressingNamespace().equals(namespace));
440: // boolean found = false;
441: // for (String name : names) {
442: // if (localName.equals(name)) {
443: // found = true;
444: // break;
445: // }
446: // }
447: // assertTrue("Unexpected header element " + localName, found);
448: // }
449: }
450:
451: private SoapMessage setUpInboundMessage(String resource)
452: throws XMLStreamException {
453: Message message = new MessageImpl();
454: SoapMessage soapMessage = new SoapMessage(message);
455: InputStream is = RMSoapInterceptorTest.class
456: .getResourceAsStream(resource);
457: assertNotNull(is);
458: XMLStreamReader reader = XMLInputFactory.newInstance()
459: .createXMLStreamReader(is);
460: soapMessage.setContent(XMLStreamReader.class, reader);
461: ReadHeadersInterceptor rji = new ReadHeadersInterceptor(
462: BusFactory.getDefaultBus());
463: rji.handleMessage(soapMessage);
464: return soapMessage;
465: }
466: }
|