1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.soap.saaj.support;
18
19 import java.util.LinkedHashMap;
20 import java.util.Map;
21 import javax.xml.soap.Name;
22 import javax.xml.soap.SOAPElement;
23 import javax.xml.soap.SOAPEnvelope;
24 import javax.xml.soap.SOAPException;
25
26 import org.springframework.util.Assert;
27 import org.springframework.util.StringUtils;
28
29 import org.xml.sax.Attributes;
30 import org.xml.sax.ContentHandler;
31 import org.xml.sax.Locator;
32 import org.xml.sax.SAXException;
33
34
35
36
37
38
39
40
41
42
43 public class SaajContentHandler implements ContentHandler {
44
45 private SOAPElement element;
46
47 private final SOAPEnvelope envelope;
48
49 private Map<String, String> namespaces = new LinkedHashMap<String, String>();
50
51
52
53
54
55
56
57 public SaajContentHandler(SOAPElement element) {
58 Assert.notNull(element, "element must not be null");
59 if (element instanceof SOAPEnvelope) {
60 envelope = (SOAPEnvelope) element;
61 }
62 else {
63 envelope = SaajUtils.getEnvelope(element);
64 }
65 this.element = element;
66 }
67
68 public void characters(char ch[], int start, int length) throws SAXException {
69 try {
70 String text = new String(ch, start, length);
71 element.addTextNode(text);
72 }
73 catch (SOAPException ex) {
74 throw new SAXException(ex);
75 }
76 }
77
78 public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
79 try {
80 String childPrefix = getPrefix(qName);
81 SOAPElement child = element.addChildElement(localName, childPrefix, uri);
82 for (int i = 0; i < atts.getLength(); i++) {
83 if (StringUtils.hasLength(atts.getLocalName(i))) {
84 String attributePrefix = getPrefix(atts.getQName(i));
85 if (!"xmlns".equals(atts.getLocalName(i)) && !"xmlns".equals(attributePrefix)) {
86 Name attributeName = envelope.createName(atts.getLocalName(i), attributePrefix, atts.getURI(i));
87 child.addAttribute(attributeName, atts.getValue(i));
88 }
89 }
90 }
91 for (String namespacePrefix : namespaces.keySet()) {
92 String namespaceUri = namespaces.get(namespacePrefix);
93 if (!findParentNamespaceDeclaration(child, namespacePrefix, namespaceUri)) {
94 child.addNamespaceDeclaration(namespacePrefix, namespaceUri);
95 }
96 }
97 element = child;
98 }
99 catch (SOAPException ex) {
100 throw new SAXException(ex);
101 }
102 }
103
104 private boolean findParentNamespaceDeclaration(SOAPElement element, String prefix, String namespaceUri) {
105 String result = element.getNamespaceURI(prefix);
106 if (namespaceUri.equals(result)) {
107 return true;
108 }
109 else {
110 try {
111 SOAPElement parent = element.getParentElement();
112 if (parent != null) {
113 return findParentNamespaceDeclaration(parent, prefix, namespaceUri);
114 }
115 }
116 catch (UnsupportedOperationException ex) {
117
118 }
119 return false;
120 }
121 }
122
123 public void endElement(String uri, String localName, String qName) throws SAXException {
124 Assert.isTrue(localName.equals(element.getElementName().getLocalName()), "Invalid element on stack");
125 Assert.isTrue(uri.equals(element.getElementName().getURI()), "Invalid element on stack");
126 element = element.getParentElement();
127 }
128
129 public void startPrefixMapping(String prefix, String uri) throws SAXException {
130 namespaces.put(prefix, uri);
131 }
132
133 public void endPrefixMapping(String prefix) throws SAXException {
134 namespaces.remove(prefix);
135 }
136
137 public void setDocumentLocator(Locator locator) {
138 }
139
140 public void startDocument() throws SAXException {
141 }
142
143 public void endDocument() throws SAXException {
144 }
145
146 public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
147 }
148
149 public void processingInstruction(String target, String data) throws SAXException {
150 }
151
152 public void skippedEntity(String name) throws SAXException {
153 }
154
155 private String getPrefix(String qName) {
156 int idx = qName.indexOf(':');
157 if (idx != -1) {
158 return qName.substring(0, idx);
159 }
160 else {
161 return null;
162 }
163 }
164 }