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.io.IOException;
20 import java.io.InputStream;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Modifier;
23 import java.util.Iterator;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26 import javax.xml.namespace.QName;
27 import javax.xml.soap.MessageFactory;
28 import javax.xml.soap.MimeHeaders;
29 import javax.xml.soap.Name;
30 import javax.xml.soap.SOAPConstants;
31 import javax.xml.soap.SOAPElement;
32 import javax.xml.soap.SOAPEnvelope;
33 import javax.xml.soap.SOAPException;
34 import javax.xml.soap.SOAPMessage;
35
36 import org.springframework.core.io.Resource;
37 import org.springframework.util.Assert;
38 import org.springframework.util.ClassUtils;
39 import org.springframework.util.StringUtils;
40 import org.springframework.ws.transport.TransportConstants;
41 import org.springframework.xml.namespace.QNameUtils;
42
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.w3c.dom.Element;
46
47
48
49
50
51
52
53
54
55
56 public abstract class SaajUtils {
57
58
59 private static final String WEBLOGIC_9_SAAJ_EXCEPTION_MESSAGE = "This class does not support SAAJ 1.1";
60
61 private static final Log logger = LogFactory.getLog(SaajUtils.class);
62
63 public static final int SAAJ_11 = 0;
64
65 public static final int SAAJ_12 = 1;
66
67 public static final int SAAJ_13 = 2;
68
69 private static final String SAAJ_13_CLASS_NAME = "javax.xml.soap.SAAJMetaFactory";
70
71
72 private static final Map<String, Integer> saajVersions = new ConcurrentHashMap<String, Integer>();
73
74 private static int saajVersion = SAAJ_12;
75
76 static {
77 if (isSaaj13()) {
78 saajVersion = SAAJ_13;
79 }
80 else if (isSaaj12()) {
81 saajVersion = SAAJ_12;
82 }
83 else {
84 saajVersion = SAAJ_11;
85 }
86 }
87
88 private static boolean isSaaj13() {
89 try {
90 ClassUtils.forName(SAAJ_13_CLASS_NAME, SaajUtils.class.getClassLoader());
91 MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
92 return true;
93 }
94 catch (ClassNotFoundException ex) {
95 return false;
96 }
97 catch (NoSuchMethodError ex) {
98 return false;
99 }
100 catch (SOAPException ex) {
101 return false;
102 }
103 }
104
105
106
107
108
109
110 private static boolean isSaaj12() {
111 if (Element.class.isAssignableFrom(SOAPElement.class)) {
112
113 try {
114 MessageFactory messageFactory = MessageFactory.newInstance();
115 SOAPMessage message = messageFactory.createMessage();
116 try {
117 message.getSOAPBody();
118 return true;
119 }
120 catch (UnsupportedOperationException ex) {
121 return false;
122 }
123 }
124 catch (SOAPException e) {
125 return false;
126 }
127 }
128 else {
129 return false;
130 }
131 }
132
133
134
135
136
137
138
139
140
141 public static int getSaajVersion() {
142 return saajVersion;
143 }
144
145
146
147
148
149
150
151
152
153 public static int getSaajVersion(SOAPMessage soapMessage) throws SOAPException {
154 Assert.notNull(soapMessage, "'soapMessage' must not be null");
155 SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
156 return getSaajVersion(soapEnvelope);
157 }
158
159
160
161
162
163
164
165
166
167 public static int getSaajVersion(SOAPElement soapElement) {
168 Assert.notNull(soapElement, "'soapElement' must not be null");
169 String soapElementClassName = soapElement.getClass().getName();
170 Integer saajVersion = saajVersions.get(soapElementClassName);
171 if (saajVersion == null) {
172 if (isSaaj12(soapElement)) {
173 if (isSaaj13(soapElement)) {
174 saajVersion = SAAJ_13;
175 }
176 else {
177 saajVersion = SAAJ_12;
178 }
179 } else {
180 saajVersion = SAAJ_11;
181 }
182 saajVersions.put(soapElementClassName, saajVersion);
183 if (logger.isTraceEnabled()) {
184 logger.trace("SOAPElement [" + soapElement.getClass().getName() + "] implements " +
185 getSaajVersionString(saajVersion));
186 }
187 }
188 return saajVersion;
189 }
190
191 private static boolean isSaaj13(SOAPElement soapElement) {
192 try {
193 Method m = soapElement.getClass().getMethod("getElementQName", new Class[0]);
194
195
196 if (Modifier.isAbstract(m.getModifiers())) {
197 logger.warn("Detected SAAJ API version 1.3, while implementation provides version 1.2. " +
198 "Please replace the SAAJ API jar with a version that corresponds to your runtime" +
199 " implementation (which might be provided by your app server).");
200 return false;
201 }
202 else {
203 return true;
204 }
205 }
206 catch (NoSuchMethodException e) {
207
208 return false;
209 }
210 }
211
212
213
214
215
216
217 private static boolean isSaaj12(SOAPElement soapElement) {
218 try {
219 Method m = soapElement.getClass().getMethod("getPrefix", new Class[0]);
220
221
222 if (Modifier.isAbstract(m.getModifiers())) {
223 logger.warn("Detected SAAJ API version 1.2, while implementation provides version 1.1. " +
224 "Please replace the SAAJ API jar with a version that corresponds to your runtime " +
225 "implementation (which might be provided by your app server).");
226 return false;
227 }
228 else {
229 soapElement.getPrefix();
230 return true;
231 }
232 }
233 catch (NoSuchMethodException e) {
234
235 return false;
236 }
237 catch (UnsupportedOperationException ex) {
238
239 if (WEBLOGIC_9_SAAJ_EXCEPTION_MESSAGE.equals(ex.getMessage())) {
240 return false;
241 } else {
242 throw ex;
243 }
244 }
245 }
246
247
248
249
250
251
252
253
254 public static String getSaajVersionString() {
255 return getSaajVersionString(saajVersion);
256 }
257
258 private static String getSaajVersionString(int saajVersion) {
259 if (saajVersion >= SaajUtils.SAAJ_13) {
260 return "SAAJ 1.3";
261 }
262 else if (saajVersion == SaajUtils.SAAJ_12) {
263 return "SAAJ 1.2";
264 }
265 else if (saajVersion == SaajUtils.SAAJ_11) {
266 return "SAAJ 1.1";
267 }
268 else {
269 return "";
270 }
271 }
272
273
274
275
276
277
278
279
280
281
282 public static Name toName(QName qName, SOAPElement resolveElement) throws SOAPException {
283 String qNamePrefix = QNameUtils.getPrefix(qName);
284 SOAPEnvelope envelope = getEnvelope(resolveElement);
285 if (StringUtils.hasLength(qName.getNamespaceURI()) && StringUtils.hasLength(qNamePrefix)) {
286 return envelope.createName(qName.getLocalPart(), qNamePrefix, qName.getNamespaceURI());
287 }
288 else if (StringUtils.hasLength(qName.getNamespaceURI())) {
289 Iterator<?> prefixes;
290 if (getSaajVersion(resolveElement) == SAAJ_11) {
291 prefixes = resolveElement.getNamespacePrefixes();
292 }
293 else {
294 prefixes = resolveElement.getVisibleNamespacePrefixes();
295 }
296 while (prefixes.hasNext()) {
297 String prefix = (String) prefixes.next();
298 if (qName.getNamespaceURI().equals(resolveElement.getNamespaceURI(prefix))) {
299 return envelope.createName(qName.getLocalPart(), prefix, qName.getNamespaceURI());
300 }
301 }
302 return envelope.createName(qName.getLocalPart(), "", qName.getNamespaceURI());
303 }
304 else {
305 return envelope.createName(qName.getLocalPart());
306 }
307 }
308
309
310
311
312
313
314
315 public static QName toQName(Name name) {
316 if (StringUtils.hasLength(name.getURI()) && StringUtils.hasLength(name.getPrefix())) {
317 return QNameUtils.createQName(name.getURI(), name.getLocalName(), name.getPrefix());
318 }
319 else if (StringUtils.hasLength(name.getURI())) {
320 return new QName(name.getURI(), name.getLocalName());
321 }
322 else {
323 return new QName(name.getLocalName());
324 }
325 }
326
327
328
329
330
331
332
333
334
335
336 public static SOAPMessage loadMessage(Resource resource, MessageFactory messageFactory)
337 throws SOAPException, IOException {
338 InputStream is = resource.getInputStream();
339 try {
340 MimeHeaders mimeHeaders = new MimeHeaders();
341 mimeHeaders.addHeader(TransportConstants.HEADER_CONTENT_TYPE, "text/xml");
342 mimeHeaders.addHeader(TransportConstants.HEADER_CONTENT_LENGTH, Long.toString(resource.getFile().length()));
343 return messageFactory.createMessage(mimeHeaders, is);
344 }
345 finally {
346 is.close();
347 }
348 }
349
350
351
352
353
354
355
356 public static SOAPEnvelope getEnvelope(SOAPElement element) {
357 Assert.notNull(element, "Element should not be null");
358 do {
359 if (element instanceof SOAPEnvelope) {
360 return (SOAPEnvelope) element;
361 }
362 element = element.getParentElement();
363 }
364 while (element != null);
365 return null;
366 }
367 }