View Javadoc

1   /*
2    * $Id: XmlMessageSplitterTestCase.java 22387 2011-07-12 03:53:36Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.routing.outbound;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.MuleMessageCollection;
17  import org.mule.api.MuleSession;
18  import org.mule.api.config.MuleProperties;
19  import org.mule.api.endpoint.OutboundEndpoint;
20  import org.mule.module.xml.routing.XmlMessageSplitter;
21  import org.mule.module.xml.util.NamespaceManager;
22  import org.mule.module.xml.util.XMLUtils;
23  import org.mule.routing.CorrelationMode;
24  import org.mule.tck.MuleTestUtils;
25  import org.mule.tck.junit4.AbstractMuleContextTestCase;
26  import org.mule.util.IOUtils;
27  
28  import com.mockobjects.constraint.Constraint;
29  import com.mockobjects.dynamic.Mock;
30  
31  import java.util.HashMap;
32  import java.util.Map;
33  
34  import javax.xml.stream.XMLInputFactory;
35  import javax.xml.transform.Source;
36  import javax.xml.transform.Transformer;
37  import javax.xml.transform.dom.DOMResult;
38  
39  import org.dom4j.Document;
40  import org.dom4j.DocumentHelper;
41  import org.junit.Test;
42  
43  import static org.junit.Assert.assertEquals;
44  import static org.junit.Assert.assertNotNull;
45  import static org.junit.Assert.assertTrue;
46  import static org.junit.Assert.fail;
47  
48  public class XmlMessageSplitterTestCase extends AbstractMuleContextTestCase
49  {
50      private OutboundEndpoint endpoint1;
51      private OutboundEndpoint endpoint2;
52      private OutboundEndpoint endpoint3;
53      private OutboundEndpoint endpoint4;
54      private OutboundEndpoint endpoint5;
55      private OutboundEndpoint endpoint6;
56      private Mock mockendpoint1;
57      private Mock mockendpoint2;
58      private Mock mockendpoint3;
59      private Mock mockendpoint4;
60      private Mock mockendpoint5;
61      private Mock mockendpoint6;
62      private XmlMessageSplitter asyncXmlSplitter;
63      private XmlMessageSplitter syncXmlSplitter;
64  
65      @Override
66      protected void doSetUp() throws Exception
67      {
68          // setup sync targets
69          endpoint1 = getTestOutboundEndpoint("Test1Endpoint", "test://endpointUri.1");
70          endpoint2 = getTestOutboundEndpoint("Test2Endpoint", "test://endpointUri.2");
71          endpoint3 = getTestOutboundEndpoint("Test3Endpoint", "test://endpointUri.3");
72          mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
73          mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
74          mockendpoint3 = RouterTestUtils.getMockEndpoint(endpoint3);
75  
76          // setup async targets
77          endpoint4 = getTestOutboundEndpoint("Test1Endpoint", "test://endpointUri.1?exchangePattern=request-response");
78          endpoint5 = getTestOutboundEndpoint("Test2Endpoint", "test://endpointUri.2?exchangePattern=request-response");
79          endpoint6 = getTestOutboundEndpoint("Test3Endpoint", "test://endpointUri.3?exchangePattern=request-response");
80          mockendpoint4 = RouterTestUtils.getMockEndpoint(endpoint4);
81          mockendpoint5 = RouterTestUtils.getMockEndpoint(endpoint5);
82          mockendpoint6 = RouterTestUtils.getMockEndpoint(endpoint6);
83  
84          // setup sync splitter
85          syncXmlSplitter = new XmlMessageSplitter();
86          syncXmlSplitter.setValidateSchema(true);
87          syncXmlSplitter.setExternalSchemaLocation("purchase-order.xsd");
88  
89          // The xml document declares a default namespace, thus
90          // we need to workaround it by specifying it both in
91          // the namespaces and in the splitExpression
92          Map namespaces = new HashMap();
93          namespaces.put("e", "http://www.example.com");
94          syncXmlSplitter.setSplitExpression("/e:purchaseOrder/e:items/e:item");
95          syncXmlSplitter.setNamespaces(namespaces);
96          syncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint4.proxy());
97          syncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint5.proxy());
98          syncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint6.proxy());
99  
100         // setup async splitter
101         asyncXmlSplitter = new XmlMessageSplitter();
102         asyncXmlSplitter.setValidateSchema(true);
103         asyncXmlSplitter.setExternalSchemaLocation("purchase-order.xsd");
104 
105         asyncXmlSplitter.setSplitExpression("/e:purchaseOrder/e:items/e:item");
106         asyncXmlSplitter.setNamespaces(namespaces);
107         asyncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint1.proxy());
108         asyncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint2.proxy());
109         asyncXmlSplitter.addRoute((OutboundEndpoint) mockendpoint3.proxy());
110 
111         syncXmlSplitter.setMuleContext(muleContext);
112         asyncXmlSplitter.setMuleContext(muleContext);
113         syncXmlSplitter.initialise();
114         asyncXmlSplitter.initialise();
115     }
116 
117     @Test
118     public void testStringPayloadXmlMessageSplitter() throws Exception
119     {
120         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
121         internalTestSuccessfulXmlSplitter(payload);
122     }
123 
124     @Test
125     public void testStringPayloadXmlMessageSplitterWithoutXsd() throws Exception
126     {
127         syncXmlSplitter.setExternalSchemaLocation(null);
128         syncXmlSplitter.setValidateSchema(false);
129         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
130         internalTestSuccessfulXmlSplitter(payload);
131     }
132 
133     @Test
134     public void testDom4JDocumentPayloadXmlMessageSplitter() throws Exception
135     {
136         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
137         Document doc = DocumentHelper.parseText(payload);
138         internalTestSuccessfulXmlSplitter(doc);
139     }
140 
141     @Test
142     public void testW3CDocumentPayloadXmlMessageSplitter() throws Exception
143     {
144         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
145         Source sourceDoc = XMLUtils.toXmlSource( XMLInputFactory.newInstance(), true, payload);
146         DOMResult result = new DOMResult();
147         Transformer transformer = XMLUtils.getTransformer();
148         transformer.transform(sourceDoc, result);
149         internalTestSuccessfulXmlSplitter(result.getNode());
150     }
151 
152     @Test
153     public void testByteArrayPayloadXmlMessageSplitter() throws Exception
154     {
155         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
156         internalTestSuccessfulXmlSplitter(payload.getBytes());
157     }
158 
159     @Test
160     public void testByteArrayPayloadCorrelateNever() throws Exception
161     {
162         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
163         syncXmlSplitter.setEnableCorrelation(CorrelationMode.NEVER);
164         asyncXmlSplitter.setEnableCorrelation(CorrelationMode.NEVER);
165         internalTestSuccessfulXmlSplitter(payload.getBytes());
166     }
167 
168     private void internalTestSuccessfulXmlSplitter(Object payload) throws Exception
169     {
170         Mock session = MuleTestUtils.getMockSession();
171         session.matchAndReturn("getFlowConstruct", getTestService());
172         session.matchAndReturn("setFlowConstruct", RouterTestUtils.getArgListCheckerFlowConstruct(), null);
173         MuleMessage message = new DefaultMuleMessage(payload, muleContext);
174 
175         assertTrue(asyncXmlSplitter.isMatch(message));
176         final ItemNodeConstraint itemNodeConstraint = new ItemNodeConstraint();
177         mockendpoint1.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
178         mockendpoint2.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
179         asyncXmlSplitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy(), muleContext));
180         mockendpoint1.verify();
181         mockendpoint2.verify();
182 
183         message = new DefaultMuleMessage(payload, muleContext);
184         MuleEvent event = new OutboundRoutingTestEvent(message, null, muleContext);
185         mockendpoint4.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
186         mockendpoint5.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
187         MuleEvent result = syncXmlSplitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy(), muleContext));
188         MuleMessage resultMessage = result.getMessage();
189         assertNotNull(resultMessage);
190         assertNotNull(result);
191         assertTrue(resultMessage instanceof MuleMessageCollection);
192         assertEquals(2, ((MuleMessageCollection) resultMessage).size());
193         mockendpoint4.verify();
194         mockendpoint5.verify();
195     }
196 
197     @Test
198     public void testXsdNotFoundThrowsException() throws Exception
199     {
200         final String invalidSchemaLocation = "non-existent.xsd";
201         Mock session = MuleTestUtils.getMockSession();
202         session.matchAndReturn("getFlowConstruct", getTestService());
203 
204         XmlMessageSplitter splitter = new XmlMessageSplitter();
205         splitter.setValidateSchema(true);
206         splitter.setExternalSchemaLocation(invalidSchemaLocation);
207 
208         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
209 
210         MuleMessage message = new DefaultMuleMessage(payload, muleContext);
211 
212         assertTrue(splitter.isMatch(message));
213         try
214         {
215             splitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy(), muleContext));
216             fail("Should have thrown an exception, because XSD is not found.");
217         }
218         catch (IllegalArgumentException iaex)
219         {
220             assertTrue("Wrong exception?", iaex.getMessage().indexOf(
221                     "Couldn't find schema at " + invalidSchemaLocation) != -1);
222         }
223         session.verify();
224     }
225 
226 
227     @Test
228     public void testInvalidPayloadTypeThrowsException() throws Exception
229     {
230         Mock session = MuleTestUtils.getMockSession();
231         session.matchAndReturn("getFlowConstruct", getTestService());
232 
233         XmlMessageSplitter splitter = new XmlMessageSplitter();
234 
235         MuleMessage message = new DefaultMuleMessage(new Exception(), muleContext);
236 
237         try
238         {
239             splitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy(), muleContext));
240             fail("No exception thrown.");
241         }
242         catch (IllegalArgumentException iaex)
243         {
244             assertTrue("Wrong exception message.", iaex.getMessage().startsWith(
245                     "Failed to initialise the payload: "));
246         }
247     }
248 
249     @Test
250     public void testInvalidXmlPayloadThrowsException() throws Exception
251     {
252         Mock session = MuleTestUtils.getMockSession();
253         session.matchAndReturn("getFlowConstruct", getTestService());
254 
255         XmlMessageSplitter splitter = new XmlMessageSplitter();
256 
257         MuleMessage message = new DefaultMuleMessage("This is not XML.", muleContext);
258 
259         try
260         {
261             splitter.route(new OutboundRoutingTestEvent(message, (MuleSession) session.proxy(), muleContext));
262             fail("No exception thrown.");
263         }
264         catch (IllegalArgumentException iaex)
265         {
266             assertTrue("Wrong exception message.", iaex.getMessage().startsWith(
267                     "Failed to initialise the payload: "));
268         }
269     }
270 
271     @Test
272     public void testGlobalNamespaceManagerLookup() throws Exception
273     {
274         // clear any configured namespaces
275         syncXmlSplitter.setNamespaces(null);
276         asyncXmlSplitter.setNamespaces(null);
277 
278         // configure a global namespace manager
279         NamespaceManager namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
280         if (namespaceManager == null)
281         {
282             namespaceManager = new NamespaceManager();
283             muleContext.getRegistry().registerObject(MuleProperties.OBJECT_MULE_NAMESPACE_MANAGER, namespaceManager);
284         }
285         Map namespaces = new HashMap();
286         namespaces.put("e", "http://www.example.com");
287         syncXmlSplitter.setSplitExpression("/e:purchaseOrder/e:items/e:item");
288         asyncXmlSplitter.setSplitExpression("/e:purchaseOrder/e:items/e:item");
289         namespaceManager.setNamespaces(namespaces);
290 
291         // re-init splitters
292         syncXmlSplitter.initialise();
293         asyncXmlSplitter.initialise();
294 
295         String payload = IOUtils.getResourceAsString("purchase-order.xml", getClass());
296         internalTestSuccessfulXmlSplitter(payload);
297     }
298 
299     private class ItemNodeConstraint implements Constraint
300     {
301         public boolean eval(Object o)
302         {
303             final MuleMessage message = (MuleMessage) o;
304             final Object payload = message.getPayload();
305             assertTrue("Wrong class type for node.", payload instanceof Document);
306 
307             // MULE-2963
308             if (syncXmlSplitter.enableCorrelation == CorrelationMode.NEVER
309                 || asyncXmlSplitter.enableCorrelation == CorrelationMode.NEVER)
310             {
311                 assertEquals(-1, message.getCorrelationGroupSize());
312             }
313             else
314             {
315                 // the purchase order document contains two parts
316                 assertEquals(2, message.getCorrelationGroupSize());
317             }
318 
319             Document node = (Document) payload;
320             final String partNumber = node.getRootElement().attributeValue("partNum");
321             return "872-AA".equals(partNumber) || "926-AA".equals(partNumber);
322         }
323     }
324 }