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