Subversion Repositories XServices

Rev

Rev 114 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
114 brianR 1
/*
2
 *   Copyright 2013 Brian Rosenberger (Brutex Network)
3
 *
4
 *   Licensed under the Apache License, Version 2.0 (the "License");
5
 *   you may not use this file except in compliance with the License.
6
 *   You may obtain a copy of the License at
7
 *
8
 *       http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *   Unless required by applicable law or agreed to in writing, software
11
 *   distributed under the License is distributed on an "AS IS" BASIS,
12
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *   See the License for the specific language governing permissions and
14
 *   limitations under the License.
15
 */
16
 
17
package net.brutex.xservices.ws.impl;
18
 
19
import java.io.ByteArrayInputStream;
20
import java.io.IOException;
21
import java.io.InputStream;
22
import java.io.StringReader;
23
import java.io.StringWriter;
127 brianR 24
import java.io.UnsupportedEncodingException;
25
import java.nio.charset.Charset;
26
import java.nio.charset.IllegalCharsetNameException;
114 brianR 27
import java.util.Iterator;
28
import java.util.List;
29
import java.util.StringTokenizer;
30
 
31
import javax.jws.WebService;
127 brianR 32
import javax.xml.namespace.QName;
114 brianR 33
import javax.xml.stream.XMLOutputFactory;
34
import javax.xml.stream.XMLStreamException;
35
import javax.xml.stream.XMLStreamReader;
36
import javax.xml.stream.XMLStreamWriter;
127 brianR 37
 
38
import net.brutex.xservices.types.AttributeType;
114 brianR 39
import net.brutex.xservices.types.NamespaceListType;
40
import net.brutex.xservices.types.NamespaceType;
127 brianR 41
import net.brutex.xservices.types.StringSplitType;
114 brianR 42
import net.brutex.xservices.types.ant.FileResource;
43
import net.brutex.xservices.ws.XServicesFault;
44
import net.brutex.xservices.ws.XmlService;
45
import org.apache.axiom.om.OMAbstractFactory;
127 brianR 46
import org.apache.axiom.om.OMAttribute;
114 brianR 47
import org.apache.axiom.om.OMCloneOptions;
127 brianR 48
import org.apache.axiom.om.OMComment;
114 brianR 49
import org.apache.axiom.om.OMContainer;
50
import org.apache.axiom.om.OMDocument;
51
import org.apache.axiom.om.OMElement;
127 brianR 52
import org.apache.axiom.om.OMFactory;
114 brianR 53
import org.apache.axiom.om.OMNode;
127 brianR 54
import org.apache.axiom.om.OMProcessingInstruction;
114 brianR 55
import org.apache.axiom.om.OMText;
56
import org.apache.axiom.om.OMXMLBuilderFactory;
57
import org.apache.axiom.om.xpath.AXIOMXPath;
58
import org.apache.log4j.Logger;
59
import org.jaxen.JaxenException;
60
import org.jaxen.SimpleNamespaceContext;
61
 
62
/**
63
 * @author Brian Rosenberger, bru(at)brutex.de
64
 *
65
 */
66
@WebService(targetNamespace = "http://ws.xservices.brutex.net", endpointInterface = "net.brutex.xservices.ws.XmlService", serviceName = "XmlService")
67
public class XmlServiceImpl implements XmlService {
68
	final Logger logger = Logger.getLogger(XmlServiceImpl.class);
69
 
70
	public String insertNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
71
		try {
72
			AXIOMXPath axp = new AXIOMXPath(xpath);
73
			InputStream is = res.getAntResource(null).getInputStream();
74
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
75
					.getDocument();
76
			OMDocument fragdoc = null;
77
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
78
				fragdoc = OMXMLBuilderFactory.createOMBuilder(
79
						new StringReader("<XS>" + xmlFragment + "</XS>"))
80
						.getDocument();
81
			} else {
82
				throw new XServicesFault("No xmldata to insert.");
83
			}
84
 
85
			// Initialize XPath context
127 brianR 86
			SimpleNamespaceContext context = createContext(nsList);
114 brianR 87
			axp.setNamespaceContext(context);
88
			axp.addNamespaces(fragdoc.getOMDocumentElement());
89
 
90
			OMDocument document = insertNodes(sourcedoc, axp, fragdoc);
91
 
92
			StringWriter sw = new StringWriter();
93
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
94
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
95
			document.serialize(writer);
96
 
97
			this.logger.trace(sw.getBuffer().toString());
98
			return sw.getBuffer().toString();
99
		} catch (JaxenException e) {
100
			e.printStackTrace();
101
			throw new XServicesFault(e);
102
		} catch (IOException e) {
103
			e.printStackTrace();
104
			throw new XServicesFault(e);
105
		} catch (XMLStreamException e) {
106
			e.printStackTrace();
107
			throw new XServicesFault(e);
108
		}
109
	}
110
 
127 brianR 111
	public String replaceNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
114 brianR 112
		try {
127 brianR 113
				AXIOMXPath axp = new AXIOMXPath(xpath);
114
				InputStream is = res.getAntResource(null).getInputStream();
115
				OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
116
				OMDocument fragdoc = null;
117
				if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
118
					fragdoc = OMXMLBuilderFactory.createOMBuilder(
119
							new StringReader("<XS>" + xmlFragment + "</XS>"))
114 brianR 120
							.getDocument();
127 brianR 121
				} else {
122
					throw new XServicesFault("No xmldata to insert.");
123
				}
114 brianR 124
 
127 brianR 125
				// Initialize XPath context
126
				SimpleNamespaceContext context = createContext(nsList);
127
				axp.setNamespaceContext(context);
128
				axp.addNamespaces(fragdoc.getOMDocumentElement());
114 brianR 129
 
127 brianR 130
				OMDocument document = replaceNodes(sourcedoc, axp, fragdoc);
114 brianR 131
 
127 brianR 132
				StringWriter sw = new StringWriter();
133
				XMLOutputFactory xof = XMLOutputFactory.newInstance();
134
				XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
135
				document.serialize(writer);
114 brianR 136
 
127 brianR 137
				this.logger.trace(sw.getBuffer().toString());
138
				return sw.getBuffer().toString();
139
			} catch (JaxenException e) {
140
				e.printStackTrace();
141
				throw new XServicesFault(e);
142
			} catch (XMLStreamException e) {
143
				e.printStackTrace();
144
				throw new XServicesFault(e);
145
			} catch (IOException e) {
146
				e.printStackTrace();
147
				throw new XServicesFault(e);
114 brianR 148
			}
149
	}
150
 
127 brianR 151
	public String replaceNodes(String source, String encoding, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
152
		encoding = validateEncoding(encoding);
114 brianR 153
		try {
154
			AXIOMXPath axp = new AXIOMXPath(xpath);
127 brianR 155
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
114 brianR 156
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
157
					.getDocument();
158
			OMDocument fragdoc = null;
159
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
160
				fragdoc = OMXMLBuilderFactory.createOMBuilder(
161
						new StringReader("<XS>" + xmlFragment + "</XS>"))
162
						.getDocument();
163
			} else {
164
				throw new XServicesFault("No xmldata to insert.");
165
			}
166
 
167
			// Initialize XPath context
127 brianR 168
			SimpleNamespaceContext context = createContext(nsList);
114 brianR 169
			axp.setNamespaceContext(context);
170
			axp.addNamespaces(fragdoc.getOMDocumentElement());
171
 
172
			OMDocument document = replaceNodes(sourcedoc, axp, fragdoc);
173
 
174
			StringWriter sw = new StringWriter();
175
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
176
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
177
			document.serialize(writer);
178
 
179
			this.logger.trace(sw.getBuffer().toString());
180
			return sw.getBuffer().toString();
181
		} catch (JaxenException e) {
182
			e.printStackTrace();
183
			throw new XServicesFault(e);
184
		} catch (XMLStreamException e) {
185
			e.printStackTrace();
186
			throw new XServicesFault(e);
127 brianR 187
		} catch (UnsupportedEncodingException e) {
188
			throw new XServicesFault(e);
114 brianR 189
		}
190
	}
191
 
127 brianR 192
	public String insertNodes(String source, String encoding, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
193
		encoding = validateEncoding(encoding);
114 brianR 194
		try {
195
			AXIOMXPath axp = new AXIOMXPath(xpath);
127 brianR 196
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
114 brianR 197
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
198
					.getDocument();
199
			OMDocument fragdoc = null;
200
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
201
				fragdoc = OMXMLBuilderFactory.createOMBuilder(
202
						new StringReader("<XS>" + xmlFragment + "</XS>"))
203
						.getDocument();
204
			} else {
205
				throw new XServicesFault("No xmldata to insert.");
206
			}
207
 
208
			// Initialize XPath context
127 brianR 209
			SimpleNamespaceContext context = createContext(nsList);
114 brianR 210
			axp.setNamespaceContext(context);
211
			axp.addNamespaces(fragdoc.getOMDocumentElement());
212
 
213
			OMDocument document = insertNodes(sourcedoc, axp, fragdoc);
214
 
215
			StringWriter sw = new StringWriter();
216
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
217
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
218
			document.serialize(writer);
219
 
220
			this.logger.trace(sw.getBuffer().toString());
221
			return sw.getBuffer().toString();
222
		} catch (JaxenException e) {
223
			e.printStackTrace();
224
			throw new XServicesFault(e);
225
		} catch (XMLStreamException e) {
226
			e.printStackTrace();
227
			throw new XServicesFault(e);
127 brianR 228
		} catch (UnsupportedEncodingException e) {
229
			throw new XServicesFault(e);
114 brianR 230
		}
231
	}
232
 
233
	public String wrapInCDATA(String data) throws XServicesFault {
234
		String result ="";
235
		String[] tokens = data.split("\\]\\]>", -1);
236
 
237
		for(int i=0; i<tokens.length; i++) {
238
			result +=  tokens[i];
239
			if (i+1 < tokens.length ) result += "]]]]><![CDATA[>";
240
		}
241
 
242
		result = "<![CDATA[" + result + "]]>";
243
		return result;
244
	}
127 brianR 245
 
246
	public StringSplitType selectXPath(String source, String encoding, NamespaceListType nsList, String xpath) throws XServicesFault {
247
		encoding = validateEncoding(encoding);
248
		try {
249
			StringSplitType rarray = new StringSplitType();
250
			AXIOMXPath axp = new AXIOMXPath(xpath);
251
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
252
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
253
 
254
			// Initialize XPath context
255
			SimpleNamespaceContext context = createContext(nsList);
256
 
257
			axp.setNamespaceContext(context);
258
			List results = axp.selectNodes(sourcedoc);
259
			for(Object o : results) {
260
				String text = null;
261
 
262
				if(o instanceof OMNode) {
263
					switch (((OMNode)o).getType()) {
264
						case OMNode.TEXT_NODE:
265
							text = ((OMText)o).getText();
266
							break;
267
						case OMNode.COMMENT_NODE:
268
							text = ((OMComment)o).getValue();
269
							break;
270
						case OMNode.PI_NODE:
271
							text = ((OMProcessingInstruction)o).getValue();
272
							break;
273
						default:
274
							StringWriter sw = new StringWriter();
275
							XMLOutputFactory xof = XMLOutputFactory.newInstance();
276
							XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
277
							((OMNode)o).serialize(writer);
278
							writer.flush();
279
							text = sw.toString();
280
					}
281
				} else if(o instanceof OMAttribute) {
282
					text = ((OMAttribute)o).getAttributeValue();
283
				} else {
284
					text = String.valueOf(o);
285
				}
286
				rarray.addStringMatch(text);
287
			}
288
 
289
 
290
			return rarray;
291
			} catch (JaxenException e) {
292
			e.printStackTrace();
293
			throw new XServicesFault(e);
294
		} catch (XMLStreamException e) {
295
				// TODO Auto-generated catch block
296
			throw new XServicesFault(e.getMessage());
297
			} catch (UnsupportedEncodingException e) {
298
				throw new XServicesFault(e);
299
		}
300
	}
301
 
302
	public String setAttribute(String source, String encoding, NamespaceListType nsList, String xpath, AttributeType attr) throws XServicesFault {
303
		encoding = validateEncoding(encoding);
304
		try {
305
			StringSplitType rarray = new StringSplitType();
306
			AXIOMXPath axp = new AXIOMXPath(xpath);
307
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
308
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
309
			OMFactory fac = OMAbstractFactory.getOMFactory();
310
 
311
			// Initialize XPath context
312
			SimpleNamespaceContext context = createContext(nsList);
313
 
314
			axp.setNamespaceContext(context);
315
			List results = axp.selectNodes(sourcedoc);
316
			for(Object o : results) {
317
				String text = null;
318
 
319
				if(o instanceof OMNode) {
320
					switch (((OMNode)o).getType()) {
321
						case OMNode.ELEMENT_NODE:
322
							OMElement node = ((OMElement)o);
323
							if(attr.value == null) {
324
								node.removeAttribute( node.getAttribute(new QName(attr.name)));
325
							} else {
326
								node.addAttribute(attr.name, attr.value, node.getNamespace());
327
							}
328
							break;
329
						default:
330
							throw new XServicesFault("XPath expression did not match an element node.");
331
					}
332
				} else {
333
					throw new XServicesFault("XPath expression did not match a node.");
334
				}
335
			}
336
 
337
			StringWriter sw = new StringWriter();
338
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
339
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
340
			sourcedoc.serialize(writer);
341
			writer.flush();
342
			return sw.toString();
343
			} catch (JaxenException e) {
344
			e.printStackTrace();
345
			throw new XServicesFault(e);
346
		} catch (XMLStreamException e) {
347
				// TODO Auto-generated catch block
348
			throw new XServicesFault(e.getMessage());
349
			} catch (UnsupportedEncodingException e) {
350
				throw new XServicesFault(e);
351
		}
352
	}
353
 
114 brianR 354
	private OMDocument insertNodes(OMDocument xmldocument, AXIOMXPath axp,OMDocument xmlfragment) throws XServicesFault {
355
		List<?> olist = null;
356
		try {
357
			olist = axp.selectNodes(xmldocument.getOMDocumentElement());
358
			this.logger.debug("XPath '" + axp.toString() + "' has "
359
					+ olist.size() + " matches.");
360
			this.logger.trace("XPath root expression is: '" + axp.debug()
361
					+ "'.");
362
		} catch (JaxenException e) {
363
			throw new XServicesFault(e.getMessage(), e);
364
		}
365
		if (olist.size() == 0)
366
			throw new XServicesFault(Messages.getString("XmlService.no_match",
367
					new Object[] { axp.toString() }));
368
 
369
		// Prepare children to insert
370
		xmlfragment.build();
371
 
372
		// Determine what has been matched
373
		OMContainer match = null;
374
		for (Object o : olist) {
375
			Iterator<?> children = xmlfragment.getOMDocumentElement()
376
					.getChildren();
377
			if ((o instanceof OMNode)) {
378
				OMNode node = (OMNode) o;
379
				switch (node.getType()) {
380
				case OMNode.ELEMENT_NODE:
381
					if ((o instanceof OMElement))
382
						match = (OMElement) o;
383
					if ((o instanceof OMDocument))
384
						match = ((OMDocument) o).getOMDocumentElement();
385
					this.logger.debug(Messages.getString("XmlService.8"));
386
					break;
387
				case OMNode.TEXT_NODE:
388
					match = ((OMText) o).getParent();
389
					this.logger.debug(Messages.getString("XmlService.9"));
390
					break;
391
				case OMNode.COMMENT_NODE:
392
					// match = node.getParent();
393
					match = (OMContainer) node;
394
					this.logger.debug(Messages.getString("XmlService.10"));
395
					break;
396
				default:
397
					this.logger.error("XPath matched "
398
							+ o.getClass().getCanonicalName() + " Node Type:"
399
							+ node.getType());
400
					this.logger.error(Messages.getString("XmlService.11"));
401
					throw new XServicesFault(
402
							Messages.getString("XmlService.12"));
403
				}
404
			} else {
405
				this.logger.error("XPath matched "
406
						+ o.getClass().getCanonicalName());
407
				this.logger.error(Messages.getString("XmlService.11"));
408
				throw new XServicesFault(Messages.getString("XmlService.12"));
409
			}
410
 
411
			while (children.hasNext()) {
412
				OMNode container = (OMNode) children.next();
413
				match.addChild((OMNode) container.clone(new OMCloneOptions()));
414
			}
415
		}
416
 
417
		xmldocument.build();
418
		return xmldocument;
419
	}
420
 
421
 
422
	private OMDocument replaceNodes(OMDocument xmldocument, AXIOMXPath axp, OMDocument xmlfragment) throws XServicesFault {
423
		List<?> olist = null;
424
		try {
425
			olist = axp.selectNodes(xmldocument.getOMDocumentElement());
426
			this.logger.debug("XPath '" + axp.toString() + "' has "
427
					+ olist.size() + " matches.");
428
			this.logger.trace("XPath root expression is: '" + axp.debug()
429
					+ "'.");
430
		} catch (JaxenException e) {
431
			throw new XServicesFault(e.getMessage(), e);
432
		}
433
		if (olist.size() == 0)
434
			throw new XServicesFault(Messages.getString("XmlService.no_match",
435
					new Object[] { axp.toString() }));
436
 
437
		// Prepare children to insert
438
		xmlfragment.build();
439
 
440
		// Determine what has been matched
441
		OMNode match = null;
442
		for (Object o : olist) {
443
			Iterator<?> children = xmlfragment.getOMDocumentElement()
444
					.getChildren();
445
			if ((o instanceof OMNode)) {
446
				OMNode node = (OMNode) o;
447
				switch (node.getType()) {
448
				case OMNode.ELEMENT_NODE:
449
					if ((o instanceof OMElement))
450
						match = (OMElement) o;
451
					if ((o instanceof OMDocument))
452
						match = ((OMDocument) o).getOMDocumentElement();
453
					this.logger.debug(Messages.getString("XmlService.8"));
454
					break;
455
				default:
456
					this.logger.error("XPath matched "
457
							+ o.getClass().getCanonicalName() + " Node Type:"
458
							+ node.getType());
459
					this.logger.error(Messages.getString("XmlService.11"));
460
					throw new XServicesFault(
461
							Messages.getString("XmlService.12"));
462
				}
463
			} else {
464
				this.logger.error("XPath matched "
465
						+ o.getClass().getCanonicalName());
466
				this.logger.error(Messages.getString("XmlService.11"));
467
				throw new XServicesFault(Messages.getString("XmlService.12"));
468
			}
469
 
470
			while (children.hasNext()) {
471
				OMNode container = (OMNode) children.next();
472
				match.insertSiblingAfter((OMNode) container.clone(new OMCloneOptions()));
473
			}
474
			match.detach();
475
		}
476
		xmldocument.build();
477
		return xmldocument;
478
	}
127 brianR 479
 
480
	private SimpleNamespaceContext createContext(NamespaceListType nsList) {
481
		// Initialize XPath context
482
		SimpleNamespaceContext context = new SimpleNamespaceContext();
483
		if(nsList != null) {
484
			for (NamespaceType ns : nsList.getNamespaces()) {
485
				context.addNamespace(ns.getPrefix(), ns.getUri().toString());
486
				this.logger.debug(Messages.getString("XmlService.0")
487
						+ ns.getPrefix() + "=\"" + ns.getUri().toString()
488
						+ "\"'");
489
			}
490
		} else {
491
			logger.debug("No namespaces defined.");
492
		}
493
		return context;
494
	}
495
 
496
	private String validateEncoding(String encoding) throws XServicesFault {
497
		if(encoding == null || encoding.equals("")) { encoding=Charset.defaultCharset().displayName(); }
498
		try {
499
			Charset.isSupported(encoding);
500
		} catch (IllegalCharsetNameException e) {
501
			throw new XServicesFault("Endcoding '"+encoding+"' is not supported by this JRE.");
502
		}
503
		logger.debug("Setting source xml string encoding to '"+encoding+"'");
504
		return encoding;
505
	}
114 brianR 506
}