1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.xml.routing;
12
13 import org.mule.api.MuleMessage;
14 import org.mule.api.lifecycle.InitialisationException;
15 import org.mule.api.registry.RegistrationException;
16 import org.mule.config.i18n.CoreMessages;
17 import org.mule.module.xml.util.NamespaceManager;
18 import org.mule.routing.CorrelationMode;
19 import org.mule.routing.outbound.AbstractRoundRobinMessageSplitter;
20 import org.mule.util.ExceptionUtils;
21 import org.mule.util.IOUtils;
22 import org.mule.util.StringUtils;
23
24 import java.io.InputStream;
25 import java.io.StringReader;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Map;
32
33 import org.dom4j.Document;
34 import org.dom4j.DocumentHelper;
35 import org.dom4j.Element;
36 import org.dom4j.Node;
37 import org.dom4j.XPath;
38 import org.dom4j.io.DOMReader;
39 import org.dom4j.io.SAXReader;
40
41
42
43
44
45
46
47
48
49
50
51
52 public class XmlMessageSplitter extends AbstractRoundRobinMessageSplitter
53 {
54
55 public static final String APACHE_XML_FEATURES_VALIDATION_SCHEMA = "http://apache.org/xml/features/validation/schema";
56 public static final String APACHE_XML_FEATURES_VALIDATION_SCHEMA_FULL_CHECKING = "http://apache.org/xml/features/validation/schema-full-checking";
57
58
59 public static final String JAXP_PROPERTIES_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
60
61
62
63 public static final String JAXP_PROPERTIES_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
64 public static final String JAXP_PROPERTIES_SCHEMA_LANGUAGE_VALUE = "http://www.w3.org/2001/XMLSchema";
65
66 protected volatile String splitExpression = "";
67 protected volatile Map<?, ?> namespaces;
68 protected NamespaceManager namespaceManager;
69
70 protected volatile boolean validateSchema;
71 protected volatile String externalSchemaLocation = "";
72
73 public void setSplitExpression(String splitExpression)
74 {
75 this.splitExpression = StringUtils.trimToEmpty(splitExpression);
76 }
77
78 public void setNamespaces(Map<?, ?> namespaces)
79 {
80 this.namespaces = namespaces;
81 }
82
83 public Map<?, ?> getNamespaces()
84 {
85 return Collections.unmodifiableMap(namespaces);
86 }
87
88 public String getSplitExpression()
89 {
90 return splitExpression;
91 }
92
93 public boolean isValidateSchema()
94 {
95 return validateSchema;
96 }
97
98 public void setValidateSchema(boolean validateSchema)
99 {
100 this.validateSchema = validateSchema;
101 }
102
103 public String getExternalSchemaLocation()
104 {
105 return externalSchemaLocation;
106 }
107
108
109
110
111
112
113
114 public void setExternalSchemaLocation(String externalSchemaLocation)
115 {
116 this.externalSchemaLocation = externalSchemaLocation;
117 }
118
119 @Override
120 public void initialise() throws InitialisationException
121 {
122 logger.warn("Deprecation warning: The XmlMessageSplitter router has been deprecating in Mule 2.2 in favour of using the <expression-splitter> router.");
123 if (StringUtils.isBlank(splitExpression))
124 {
125 throw new IllegalArgumentException(CoreMessages.objectIsNull("splitExpression").getMessage());
126 }
127
128 try
129 {
130 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
131
132 if (namespaceManager != null)
133 {
134 if (namespaces == null)
135 {
136 namespaces = new HashMap<Object, Object>(namespaceManager.getNamespaces());
137 }
138 else
139 {
140 namespaces.putAll(namespaceManager.getNamespaces());
141 }
142 }
143
144 }
145 catch (RegistrationException e)
146 {
147 throw new InitialisationException(CoreMessages.failedToLoad("NamespaceManager"), e, this);
148 }
149
150 super.initialise();
151 }
152
153
154
155
156
157
158
159 @Override
160 protected List splitMessage(MuleMessage message)
161 {
162 if (logger.isDebugEnabled())
163 {
164 if (splitExpression.length() == 0)
165 {
166 logger.warn("splitExpression is not specified, no processing will take place");
167 }
168 else
169 {
170 logger.debug("splitExpression is " + splitExpression);
171 }
172 }
173
174 Object src = message.getPayload();
175
176 try
177 {
178 if (src instanceof byte[])
179 {
180 src = new String((byte[]) src);
181 }
182
183 Document dom4jDoc;
184
185 if (src instanceof String)
186 {
187 String xml = (String) src;
188 SAXReader reader = new SAXReader();
189 setDoSchemaValidation(reader, isValidateSchema());
190
191 dom4jDoc = reader.read(new StringReader(xml));
192 }
193 else if (src instanceof org.dom4j.Document)
194 {
195 dom4jDoc = (org.dom4j.Document) src;
196 }
197 else if (src instanceof org.w3c.dom.Document)
198 {
199 DOMReader xmlReader = new DOMReader();
200 dom4jDoc = xmlReader.read((org.w3c.dom.Document)src);
201 }
202 else
203 {
204 throw new IllegalArgumentException(CoreMessages.objectNotOfCorrectType(
205 src.getClass(), new Class[]{org.w3c.dom.Document.class, Document.class, String.class, byte[].class}).getMessage());
206 }
207
208 XPath xpath = dom4jDoc.createXPath(splitExpression);
209 if (namespaces != null)
210 {
211 xpath.setNamespaceURIs(namespaces);
212 }
213
214 List foundNodes = xpath.selectNodes(dom4jDoc);
215 if (enableCorrelation != CorrelationMode.NEVER)
216 {
217 message.setCorrelationGroupSize(foundNodes.size());
218 }
219 if (logger.isDebugEnabled())
220 {
221 logger.debug("Split into " + foundNodes.size());
222 }
223
224 List parts = new LinkedList();
225
226
227
228 for (Iterator iterator = foundNodes.iterator(); iterator.hasNext();)
229 {
230 Node node = (Node) iterator.next();
231 if (node instanceof Element)
232 {
233
234
235 node = (Node) node.clone();
236 parts.add(DocumentHelper.createDocument((Element) node));
237 }
238 else
239 {
240 logger.warn("Dcoument node: " + node.asXML()
241 + " is not an element and thus is not a valid part");
242 }
243 }
244 return parts;
245 }
246 catch (Exception ex)
247 {
248 throw new IllegalArgumentException("Failed to initialise the payload: "
249 + ExceptionUtils.getStackTrace(ex));
250 }
251 }
252
253 protected void setDoSchemaValidation(SAXReader reader, boolean validate) throws Exception
254 {
255 reader.setValidation(validate);
256 reader.setFeature(APACHE_XML_FEATURES_VALIDATION_SCHEMA, validate);
257 reader.setFeature(APACHE_XML_FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, true);
258
259
260
261 if (!validate)
262 {
263 return;
264 }
265
266 InputStream xsdAsStream = IOUtils.getResourceAsStream(getExternalSchemaLocation(), getClass());
267 if (xsdAsStream == null)
268 {
269 throw new IllegalArgumentException("Couldn't find schema at "
270 + getExternalSchemaLocation());
271 }
272
273
274
275 reader.setProperty(JAXP_PROPERTIES_SCHEMA_LANGUAGE, JAXP_PROPERTIES_SCHEMA_LANGUAGE_VALUE);
276
277
278 reader.setProperty(JAXP_PROPERTIES_SCHEMA_SOURCE, xsdAsStream);
279 }
280 }