1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.xml.routing;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.endpoint.OutboundEndpoint;
16 import org.mule.module.xml.util.XMLUtils;
17 import org.mule.routing.outbound.AbstractMessageSplitter;
18 import org.mule.util.ExceptionUtils;
19 import org.mule.util.StringUtils;
20
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.dom4j.Document;
29 import org.dom4j.DocumentHelper;
30 import org.dom4j.Element;
31 import org.dom4j.Node;
32 import org.dom4j.XPath;
33
34
35
36
37
38
39
40
41
42
43
44
45 public class FilteringXmlMessageSplitter extends AbstractMessageSplitter
46 {
47 protected final ThreadLocal propertiesContext = new ThreadLocal();
48 protected final ThreadLocal nodesContext = new ThreadLocal();
49
50 protected volatile String splitExpression = "";
51 protected volatile Map namespaces = null;
52 protected volatile boolean validateSchema = false;
53 protected volatile String externalSchemaLocation = "";
54
55 public void setSplitExpression(String splitExpression)
56 {
57 this.splitExpression = StringUtils.trimToEmpty(splitExpression);
58 }
59
60 public void setNamespaces(Map namespaces)
61 {
62 this.namespaces = namespaces;
63 }
64
65 public Map getNamespaces()
66 {
67 return Collections.unmodifiableMap(namespaces);
68 }
69
70 public String getSplitExpression()
71 {
72 return splitExpression;
73 }
74
75 public boolean isValidateSchema()
76 {
77 return validateSchema;
78 }
79
80 public void setValidateSchema(boolean validateSchema)
81 {
82 this.validateSchema = validateSchema;
83 }
84
85 public String getExternalSchemaLocation()
86 {
87 return externalSchemaLocation;
88 }
89
90
91
92
93
94
95
96 public void setExternalSchemaLocation(String externalSchemaLocation)
97 {
98 this.externalSchemaLocation = externalSchemaLocation;
99 }
100
101
102
103
104
105
106
107
108 protected void initialise(MuleMessage message)
109 {
110 if (logger.isDebugEnabled())
111 {
112 if (splitExpression.length() == 0)
113 {
114 logger.warn("splitExpression is not specified, no processing will take place");
115 }
116 else
117 {
118 logger.debug("splitExpression is " + splitExpression);
119 }
120 }
121
122 Object src = message.getPayload();
123
124 Document dom4jDoc;
125 try
126 {
127 if (validateSchema)
128 {
129 dom4jDoc = XMLUtils.toDocument(src, getExternalSchemaLocation());
130 }
131 else
132 {
133 dom4jDoc = XMLUtils.toDocument(src);
134 }
135 if (dom4jDoc == null)
136 {
137 logger.error("Non-XML message payload: " + src.getClass().toString());
138 return;
139 }
140 }
141 catch (Exception e)
142 {
143 throw new IllegalArgumentException("Failed to initialise the payload: "
144 + ExceptionUtils.getStackTrace(e));
145 }
146
147 if (splitExpression.length() > 0)
148 {
149 XPath xpath = dom4jDoc.createXPath(splitExpression);
150 if (namespaces != null)
151 {
152 xpath.setNamespaceURIs(namespaces);
153 }
154
155 List foundNodes = xpath.selectNodes(dom4jDoc);
156 if (enableCorrelation != ENABLE_CORRELATION_NEVER)
157 {
158 message.setCorrelationGroupSize(foundNodes.size());
159 }
160 if (logger.isDebugEnabled())
161 {
162 logger.debug("Split into " + foundNodes.size());
163 }
164
165 List parts = new LinkedList();
166
167
168
169 for (Iterator iterator = foundNodes.iterator(); iterator.hasNext();)
170 {
171 Node node = (Node)iterator.next();
172 if (node instanceof Element)
173 {
174
175
176 node = (Node)node.clone();
177 parts.add(DocumentHelper.createDocument((Element)node));
178 }
179 else
180 {
181 logger.warn("Dcoument node: " + node.asXML()
182 + " is not an element and thus is not a valid part");
183 }
184 }
185 nodesContext.set(parts);
186 }
187
188 Map theProperties = new HashMap();
189 for (Iterator iterator = message.getPropertyNames().iterator(); iterator.hasNext();)
190 {
191 String propertyKey = (String)iterator.next();
192 theProperties.put(propertyKey, message.getProperty(propertyKey));
193 }
194 propertiesContext.set(theProperties);
195 }
196
197
198 protected void cleanup()
199 {
200 nodesContext.set(null);
201 propertiesContext.set(null);
202 }
203
204
205
206
207
208
209
210
211
212
213 protected MuleMessage getMessagePart(MuleMessage message, OutboundEndpoint endpoint)
214 {
215 List nodes = (List)nodesContext.get();
216
217 if (nodes == null)
218 {
219 logger.error("Error: nodes are null");
220 return null;
221 }
222
223 for (Iterator i = nodes.iterator(); i.hasNext();)
224 {
225 Document doc = (Document)i.next();
226
227 try
228 {
229 Map theProperties = (Map)propertiesContext.get();
230 MuleMessage result = new DefaultMuleMessage(doc, new HashMap(theProperties));
231
232 if (endpoint.getFilter() == null || endpoint.getFilter().accept(result))
233 {
234 if (logger.isDebugEnabled())
235 {
236 logger.debug("Endpoint filter matched for node " + i + " of " + nodes.size()
237 + ". Routing message over: " + endpoint.getEndpointURI().toString());
238 }
239 i.remove();
240 return result;
241 }
242 else
243 {
244 if (logger.isDebugEnabled())
245 {
246 logger.debug("Endpoint filter did not match, returning null");
247 }
248 }
249 }
250 catch (Exception e)
251 {
252 logger.error("Unable to create message for node at position " + i, e);
253 return null;
254 }
255 }
256
257 return null;
258 }
259 }