Subversion Repositories XServices

Rev

Rev 198 | 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 javax.jws.WebService;
127 brianR 30
import javax.xml.namespace.QName;
114 brianR 31
import javax.xml.stream.XMLOutputFactory;
32
import javax.xml.stream.XMLStreamException;
33
import javax.xml.stream.XMLStreamWriter;
127 brianR 34
 
199 brianR 35
import lombok.extern.slf4j.Slf4j;
127 brianR 36
import net.brutex.xservices.types.AttributeType;
114 brianR 37
import net.brutex.xservices.types.NamespaceListType;
38
import net.brutex.xservices.types.NamespaceType;
127 brianR 39
import net.brutex.xservices.types.StringSplitType;
114 brianR 40
import net.brutex.xservices.types.ant.FileResource;
41
import net.brutex.xservices.ws.XServicesFault;
42
import net.brutex.xservices.ws.XmlService;
158 brianR 43
 
114 brianR 44
import org.apache.axiom.om.OMAbstractFactory;
127 brianR 45
import org.apache.axiom.om.OMAttribute;
114 brianR 46
import org.apache.axiom.om.OMCloneOptions;
127 brianR 47
import org.apache.axiom.om.OMComment;
114 brianR 48
import org.apache.axiom.om.OMContainer;
49
import org.apache.axiom.om.OMDocument;
50
import org.apache.axiom.om.OMElement;
127 brianR 51
import org.apache.axiom.om.OMFactory;
114 brianR 52
import org.apache.axiom.om.OMNode;
127 brianR 53
import org.apache.axiom.om.OMProcessingInstruction;
114 brianR 54
import org.apache.axiom.om.OMText;
55
import org.apache.axiom.om.OMXMLBuilderFactory;
56
import org.apache.axiom.om.xpath.AXIOMXPath;
185 brianR 57
 
199 brianR 58
 
177 brianR 59
import org.apache.shiro.authz.annotation.RequiresPermissions;
114 brianR 60
import org.jaxen.JaxenException;
61
import org.jaxen.SimpleNamespaceContext;
62
 
63
/**
64
 * @author Brian Rosenberger, bru(at)brutex.de
65
 *
66
 */
199 brianR 67
@Slf4j
114 brianR 68
@WebService(targetNamespace = "http://ws.xservices.brutex.net", endpointInterface = "net.brutex.xservices.ws.XmlService", serviceName = "XmlService")
69
public class XmlServiceImpl implements XmlService {
70
 
199 brianR 71
 
185 brianR 72
	public String insertNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String xmlFragment)
73
			throws XServicesFault {
114 brianR 74
		try {
75
			AXIOMXPath axp = new AXIOMXPath(xpath);
76
			InputStream is = res.getAntResource(null).getInputStream();
185 brianR 77
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
114 brianR 78
			OMDocument fragdoc = null;
79
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
185 brianR 80
				fragdoc = OMXMLBuilderFactory.createOMBuilder(new StringReader("<XS>" + xmlFragment + "</XS>"))
114 brianR 81
						.getDocument();
82
			} else {
83
				throw new XServicesFault("No xmldata to insert.");
84
			}
85
 
86
			// Initialize XPath context
127 brianR 87
			SimpleNamespaceContext context = createContext(nsList);
114 brianR 88
			axp.setNamespaceContext(context);
89
			axp.addNamespaces(fragdoc.getOMDocumentElement());
90
 
91
			OMDocument document = insertNodes(sourcedoc, axp, fragdoc);
92
 
93
			StringWriter sw = new StringWriter();
94
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
95
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
96
			document.serialize(writer);
97
 
199 brianR 98
			log.debug(sw.getBuffer().toString());
114 brianR 99
			return sw.getBuffer().toString();
100
		} catch (JaxenException e) {
101
			e.printStackTrace();
102
			throw new XServicesFault(e);
103
		} catch (IOException e) {
104
			e.printStackTrace();
105
			throw new XServicesFault(e);
106
		} catch (XMLStreamException e) {
107
			e.printStackTrace();
108
			throw new XServicesFault(e);
109
		}
110
	}
111
 
185 brianR 112
	public String replaceNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String xmlFragment)
113
			throws XServicesFault {
114 brianR 114
		try {
185 brianR 115
			AXIOMXPath axp = new AXIOMXPath(xpath);
116
			InputStream is = res.getAntResource(null).getInputStream();
117
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
118
			OMDocument fragdoc = null;
119
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
120
				fragdoc = OMXMLBuilderFactory.createOMBuilder(new StringReader("<XS>" + xmlFragment + "</XS>"))
121
						.getDocument();
122
			} else {
123
				throw new XServicesFault("No xmldata to insert.");
124
			}
114 brianR 125
 
185 brianR 126
			// Initialize XPath context
127
			SimpleNamespaceContext context = createContext(nsList);
128
			axp.setNamespaceContext(context);
129
			axp.addNamespaces(fragdoc.getOMDocumentElement());
114 brianR 130
 
185 brianR 131
			OMDocument document = replaceNodes(sourcedoc, axp, fragdoc);
114 brianR 132
 
185 brianR 133
			StringWriter sw = new StringWriter();
134
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
135
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
136
			document.serialize(writer);
114 brianR 137
 
199 brianR 138
			log.debug(sw.getBuffer().toString());
185 brianR 139
			return sw.getBuffer().toString();
140
		} catch (JaxenException e) {
141
			e.printStackTrace();
142
			throw new XServicesFault(e);
143
		} catch (XMLStreamException e) {
144
			e.printStackTrace();
145
			throw new XServicesFault(e);
146
		} catch (IOException e) {
147
			e.printStackTrace();
148
			throw new XServicesFault(e);
149
		}
114 brianR 150
	}
151
 
185 brianR 152
	public String replaceNodes(String source, String encoding, NamespaceListType nsList, String xpath,
153
			String xmlFragment) throws XServicesFault {
127 brianR 154
		encoding = validateEncoding(encoding);
114 brianR 155
		try {
156
			AXIOMXPath axp = new AXIOMXPath(xpath);
127 brianR 157
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
185 brianR 158
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
114 brianR 159
			OMDocument fragdoc = null;
160
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
185 brianR 161
				fragdoc = OMXMLBuilderFactory.createOMBuilder(new StringReader("<XS>" + xmlFragment + "</XS>"))
114 brianR 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
 
199 brianR 179
			log.debug(sw.getBuffer().toString());
114 brianR 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
	}
185 brianR 191
 
177 brianR 192
	@RequiresPermissions("insertNodes")
185 brianR 193
	public String insertNodes(String source, String encoding, NamespaceListType nsList, String xpath,
194
			String xmlFragment) throws XServicesFault {
127 brianR 195
		encoding = validateEncoding(encoding);
114 brianR 196
		try {
197
			AXIOMXPath axp = new AXIOMXPath(xpath);
127 brianR 198
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
185 brianR 199
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
114 brianR 200
			OMDocument fragdoc = null;
201
			if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
185 brianR 202
				fragdoc = OMXMLBuilderFactory.createOMBuilder(new StringReader("<XS>" + xmlFragment + "</XS>"))
114 brianR 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
 
199 brianR 220
			log.debug(sw.getBuffer().toString());
114 brianR 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 {
185 brianR 234
		String result = "";
114 brianR 235
		String[] tokens = data.split("\\]\\]>", -1);
185 brianR 236
 
237
		for (int i = 0; i < tokens.length; i++) {
238
			result += tokens[i];
239
			if (i + 1 < tokens.length)
240
				result += "]]]]><![CDATA[>";
114 brianR 241
		}
185 brianR 242
 
114 brianR 243
		result = "<![CDATA[" + result + "]]>";
244
		return result;
245
	}
127 brianR 246
 
185 brianR 247
	public StringSplitType selectXPath(String source, String encoding, NamespaceListType nsList, String xpath)
248
			throws XServicesFault {
127 brianR 249
		encoding = validateEncoding(encoding);
250
		try {
251
			StringSplitType rarray = new StringSplitType();
252
			AXIOMXPath axp = new AXIOMXPath(xpath);
253
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
254
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
185 brianR 255
 
127 brianR 256
			// Initialize XPath context
257
			SimpleNamespaceContext context = createContext(nsList);
185 brianR 258
 
127 brianR 259
			axp.setNamespaceContext(context);
260
			List results = axp.selectNodes(sourcedoc);
185 brianR 261
			for (Object o : results) {
127 brianR 262
				String text = null;
185 brianR 263
 
264
				if (o instanceof OMNode) {
265
					switch (((OMNode) o).getType()) {
266
					case OMNode.TEXT_NODE:
267
						text = ((OMText) o).getText();
268
						break;
269
					case OMNode.COMMENT_NODE:
270
						text = ((OMComment) o).getValue();
271
						break;
272
					case OMNode.PI_NODE:
273
						text = ((OMProcessingInstruction) o).getValue();
274
						break;
275
					default:
276
						StringWriter sw = new StringWriter();
277
						XMLOutputFactory xof = XMLOutputFactory.newInstance();
278
						XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
279
						((OMNode) o).serialize(writer);
280
						writer.flush();
281
						text = sw.toString();
282
					}
283
				} else if (o instanceof OMAttribute) {
284
					text = ((OMAttribute) o).getAttributeValue();
127 brianR 285
				} else {
286
					text = String.valueOf(o);
287
				}
288
				rarray.addStringMatch(text);
289
			}
290
 
291
			return rarray;
185 brianR 292
		} catch (JaxenException e) {
127 brianR 293
			e.printStackTrace();
294
			throw new XServicesFault(e);
295
		} catch (XMLStreamException e) {
185 brianR 296
			// TODO Auto-generated catch block
127 brianR 297
			throw new XServicesFault(e.getMessage());
185 brianR 298
		} catch (UnsupportedEncodingException e) {
299
			throw new XServicesFault(e);
127 brianR 300
		}
301
	}
185 brianR 302
 
303
	public String setAttribute(String source, String encoding, NamespaceListType nsList, String xpath,
304
			AttributeType attr) throws XServicesFault {
127 brianR 305
		encoding = validateEncoding(encoding);
306
		try {
307
			StringSplitType rarray = new StringSplitType();
308
			AXIOMXPath axp = new AXIOMXPath(xpath);
309
			InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
310
			OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
311
			OMFactory fac = OMAbstractFactory.getOMFactory();
185 brianR 312
 
127 brianR 313
			// Initialize XPath context
314
			SimpleNamespaceContext context = createContext(nsList);
185 brianR 315
 
127 brianR 316
			axp.setNamespaceContext(context);
317
			List results = axp.selectNodes(sourcedoc);
185 brianR 318
			for (Object o : results) {
127 brianR 319
				String text = null;
185 brianR 320
 
321
				if (o instanceof OMNode) {
322
					switch (((OMNode) o).getType()) {
323
					case OMNode.ELEMENT_NODE:
324
						OMElement node = ((OMElement) o);
325
						if (attr.value == null) {
326
							node.removeAttribute(node.getAttribute(new QName(attr.name)));
327
						} else {
328
							node.addAttribute(attr.name, attr.value, node.getNamespace());
329
						}
330
						break;
331
					default:
332
						throw new XServicesFault("XPath expression did not match an element node.");
127 brianR 333
					}
334
				} else {
335
					throw new XServicesFault("XPath expression did not match a node.");
336
				}
337
			}
185 brianR 338
 
127 brianR 339
			StringWriter sw = new StringWriter();
340
			XMLOutputFactory xof = XMLOutputFactory.newInstance();
341
			XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
342
			sourcedoc.serialize(writer);
343
			writer.flush();
185 brianR 344
			return sw.toString();
345
		} catch (JaxenException e) {
127 brianR 346
			e.printStackTrace();
347
			throw new XServicesFault(e);
348
		} catch (XMLStreamException e) {
185 brianR 349
			// TODO Auto-generated catch block
127 brianR 350
			throw new XServicesFault(e.getMessage());
185 brianR 351
		} catch (UnsupportedEncodingException e) {
352
			throw new XServicesFault(e);
127 brianR 353
		}
354
	}
185 brianR 355
 
356
	private OMDocument insertNodes(OMDocument xmldocument, AXIOMXPath axp, OMDocument xmlfragment)
357
			throws XServicesFault {
114 brianR 358
		List<?> olist = null;
359
		try {
360
			olist = axp.selectNodes(xmldocument.getOMDocumentElement());
199 brianR 361
			log.debug("XPath '" + axp.toString() + "' has " + olist.size() + " matches.");
362
			log.debug("XPath root expression is: '" + axp.debug() + "'.");
114 brianR 363
		} catch (JaxenException e) {
364
			throw new XServicesFault(e.getMessage(), e);
365
		}
366
		if (olist.size() == 0)
185 brianR 367
			throw new XServicesFault(Messages.getString("XmlService.no_match", new Object[] { axp.toString() }));
114 brianR 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) {
185 brianR 375
			Iterator<?> children = xmlfragment.getOMDocumentElement().getChildren();
114 brianR 376
			if ((o instanceof OMNode)) {
377
				OMNode node = (OMNode) o;
378
				switch (node.getType()) {
379
				case OMNode.ELEMENT_NODE:
380
					if ((o instanceof OMElement))
381
						match = (OMElement) o;
382
					if ((o instanceof OMDocument))
383
						match = ((OMDocument) o).getOMDocumentElement();
199 brianR 384
					log.debug(Messages.getString("XmlService.8"));
114 brianR 385
					break;
386
				case OMNode.TEXT_NODE:
387
					match = ((OMText) o).getParent();
199 brianR 388
					log.debug(Messages.getString("XmlService.9"));
114 brianR 389
					break;
390
				case OMNode.COMMENT_NODE:
391
					// match = node.getParent();
392
					match = (OMContainer) node;
199 brianR 393
					log.debug(Messages.getString("XmlService.10"));
114 brianR 394
					break;
395
				default:
199 brianR 396
					log.error("XPath matched " + o.getClass().getCanonicalName() + " Node Type:" + node.getType());
397
					log.error(Messages.getString("XmlService.11"));
185 brianR 398
					throw new XServicesFault(Messages.getString("XmlService.12"));
114 brianR 399
				}
400
			} else {
199 brianR 401
				log.error("XPath matched " + o.getClass().getCanonicalName());
402
				log.error(Messages.getString("XmlService.11"));
114 brianR 403
				throw new XServicesFault(Messages.getString("XmlService.12"));
404
			}
405
 
406
			while (children.hasNext()) {
407
				OMNode container = (OMNode) children.next();
408
				match.addChild((OMNode) container.clone(new OMCloneOptions()));
409
			}
410
		}
411
 
412
		xmldocument.build();
413
		return xmldocument;
414
	}
415
 
185 brianR 416
	private OMDocument replaceNodes(OMDocument xmldocument, AXIOMXPath axp, OMDocument xmlfragment)
417
			throws XServicesFault {
114 brianR 418
 
419
		List<?> olist = null;
420
		try {
421
			olist = axp.selectNodes(xmldocument.getOMDocumentElement());
199 brianR 422
			log.debug("XPath '" + axp.toString() + "' has " + olist.size() + " matches.");
423
			log.debug("XPath root expression is: '" + axp.debug() + "'.");
114 brianR 424
		} catch (JaxenException e) {
425
			throw new XServicesFault(e.getMessage(), e);
426
		}
427
		if (olist.size() == 0)
185 brianR 428
			throw new XServicesFault(Messages.getString("XmlService.no_match", new Object[] { axp.toString() }));
114 brianR 429
 
430
		// Prepare children to insert
431
		xmlfragment.build();
432
 
433
		// Determine what has been matched
434
		OMNode match = null;
435
		for (Object o : olist) {
185 brianR 436
			Iterator<?> children = xmlfragment.getOMDocumentElement().getChildren();
114 brianR 437
			if ((o instanceof OMNode)) {
438
				OMNode node = (OMNode) o;
439
				switch (node.getType()) {
440
				case OMNode.ELEMENT_NODE:
441
					if ((o instanceof OMElement))
442
						match = (OMElement) o;
443
					if ((o instanceof OMDocument))
444
						match = ((OMDocument) o).getOMDocumentElement();
199 brianR 445
					log.debug(Messages.getString("XmlService.8"));
114 brianR 446
					break;
447
				default:
199 brianR 448
					log.error("XPath matched " + o.getClass().getCanonicalName() + " Node Type:" + node.getType());
449
					log.error(Messages.getString("XmlService.11"));
185 brianR 450
					throw new XServicesFault(Messages.getString("XmlService.12"));
114 brianR 451
				}
452
			} else {
199 brianR 453
				log.error("XPath matched " + o.getClass().getCanonicalName());
454
				log.error(Messages.getString("XmlService.11"));
114 brianR 455
				throw new XServicesFault(Messages.getString("XmlService.12"));
456
			}
457
 
458
			while (children.hasNext()) {
459
				OMNode container = (OMNode) children.next();
158 brianR 460
				match.insertSiblingBefore((OMNode) container.clone(new OMCloneOptions()));
114 brianR 461
			}
462
			match.detach();
463
		}
464
		xmldocument.build();
465
		return xmldocument;
466
	}
127 brianR 467
 
468
	private SimpleNamespaceContext createContext(NamespaceListType nsList) {
469
		// Initialize XPath context
470
		SimpleNamespaceContext context = new SimpleNamespaceContext();
185 brianR 471
		if (nsList != null) {
127 brianR 472
			for (NamespaceType ns : nsList.getNamespaces()) {
473
				context.addNamespace(ns.getPrefix(), ns.getUri().toString());
199 brianR 474
				log.debug(
185 brianR 475
						Messages.getString("XmlService.0") + ns.getPrefix() + "=\"" + ns.getUri().toString() + "\"'");
127 brianR 476
			}
477
		} else {
199 brianR 478
			log.debug("No namespaces defined.");
127 brianR 479
		}
480
		return context;
481
	}
482
 
483
	private String validateEncoding(String encoding) throws XServicesFault {
185 brianR 484
		if (encoding == null || encoding.equals("")) {
485
			encoding = Charset.defaultCharset().displayName();
486
		}
487
		try {
127 brianR 488
			Charset.isSupported(encoding);
489
		} catch (IllegalCharsetNameException e) {
185 brianR 490
			throw new XServicesFault("Endcoding '" + encoding + "' is not supported by this JRE.");
127 brianR 491
		}
199 brianR 492
		log.debug("Setting source xml string encoding to '" + encoding + "'");
127 brianR 493
		return encoding;
494
	}
158 brianR 495
 
114 brianR 496
}