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