1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.openehealth.ipf.commons.ihe.ws.cxf.payload;
17
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 import javax.xml.XMLConstants;
24
25 import org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor;
26 import org.apache.cxf.interceptor.Fault;
27 import org.apache.cxf.message.Message;
28 import org.apache.cxf.phase.AbstractPhaseInterceptor;
29 import org.apache.cxf.phase.Phase;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.NamedNodeMap;
33 import org.w3c.dom.Node;
34
35 import static org.openehealth.ipf.commons.ihe.ws.cxf.payload.StringPayloadHolder.PayloadType.SOAP_BODY;
36
37
38
39
40
41
42
43 public class InNamespaceMergeInterceptor extends AbstractPhaseInterceptor<Message> {
44
45 private final static Pattern XMLNS_PATTERN = Pattern.compile("xmlns:(\\w+)=\".+?\"");
46
47 public InNamespaceMergeInterceptor() {
48 super(Phase.UNMARSHAL);
49 addAfter(DocLiteralInInterceptor.class.getName());
50 }
51
52 @Override
53 public void handleMessage(Message message) throws Fault {
54 if (isGET(message)) {
55 return;
56 }
57
58 StringPayloadHolder payloadHolder = message.getContent(StringPayloadHolder.class);
59 if (payloadHolder != null) {
60 String payload = payloadHolder.get(SOAP_BODY);
61 if (isXmlContent(payload)) {
62 Document document = (Document) message.getContent(Node.class);
63 if (document != null) {
64
65
66
67
68
69
70 payloadHolder.put(SOAP_BODY, enrichNamespaces(document, payload));
71 }
72 }
73 }
74 }
75
76
77
78
79
80 private static boolean isXmlContent(String payload) {
81 if (payload != null) {
82 for (int i = 0; i < payload.length(); ++i) {
83 char c = payload.charAt(i);
84 if (!Character.isWhitespace(c)) {
85 return (c == '<');
86 }
87 }
88 }
89 return false;
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 protected static String enrichNamespaces(Document source, String target) {
110 Map<String, String> namespaces = new HashMap<>();
111
112
113 Element envelope = source.getDocumentElement();
114 addNamespacesFromElement(envelope, namespaces);
115
116
117 Node node = envelope.getFirstChild();
118 while ((node != null) && !((node instanceof Element) && "Body".equals(node.getLocalName()))) {
119 node = node.getNextSibling();
120 }
121 Element body = (Element) node;
122 addNamespacesFromElement(body, namespaces);
123
124 if (!namespaces.isEmpty()) {
125
126 int startPos = 0;
127 int endPos = target.indexOf('>');
128 while ((endPos != -1) && "--".equals(target.substring(endPos - 2, endPos))) {
129 startPos = endPos + 1;
130 endPos = target.indexOf('>', startPos);
131 }
132 if (endPos == -1) {
133 return target;
134 }
135 if (target.charAt(endPos - 1) == '/') {
136 --endPos;
137 }
138
139
140 String startTag = target.substring(startPos, endPos);
141 Matcher matcher = XMLNS_PATTERN.matcher(startTag);
142 while (matcher.find()) {
143 namespaces.remove(matcher.group(1));
144 }
145
146
147 if (!namespaces.isEmpty()) {
148 StringBuilder sb = new StringBuilder(startTag);
149 for (Map.Entry<String, String> ns : namespaces.entrySet()) {
150 sb.append(" xmlns:").append(ns.getKey()).append("=\"")
151 .append(ns.getValue()).append('"');
152 }
153 sb.append(target.substring(endPos));
154 return sb.toString();
155 }
156 }
157
158 return target;
159 }
160
161
162
163
164
165
166
167
168 protected static void addNamespacesFromElement(Element elem, Map<String, String> map) {
169 NamedNodeMap attributes = elem.getAttributes();
170 for (int i = 0; i < attributes.getLength(); ++i) {
171 Node attribute = attributes.item(i);
172 if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attribute.getNamespaceURI())) {
173 map.put(attribute.getLocalName(), attribute.getTextContent());
174 }
175 }
176 }
177
178 }