1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.soap.saaj;
18
19 import java.io.BufferedInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.PushbackInputStream;
23 import java.util.Iterator;
24 import java.util.StringTokenizer;
25 import javax.xml.soap.MessageFactory;
26 import javax.xml.soap.MimeHeaders;
27 import javax.xml.soap.SOAPConstants;
28 import javax.xml.soap.SOAPException;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import org.springframework.beans.factory.InitializingBean;
34 import org.springframework.util.StringUtils;
35 import org.springframework.ws.WebServiceMessage;
36 import org.springframework.ws.soap.SoapMessageCreationException;
37 import org.springframework.ws.soap.SoapMessageFactory;
38 import org.springframework.ws.soap.SoapVersion;
39 import org.springframework.ws.soap.saaj.support.SaajUtils;
40 import org.springframework.ws.transport.TransportConstants;
41 import org.springframework.ws.transport.TransportInputStream;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingBean {
57
58 private static final Log logger = LogFactory.getLog(SaajSoapMessageFactory.class);
59
60 private MessageFactory messageFactory;
61
62 private String messageFactoryProtocol;
63
64 private boolean langAttributeOnSoap11FaultString = true;
65
66
67 public SaajSoapMessageFactory() {
68 }
69
70
71 public SaajSoapMessageFactory(MessageFactory messageFactory) {
72 this.messageFactory = messageFactory;
73 }
74
75
76 public MessageFactory getMessageFactory() {
77 return messageFactory;
78 }
79
80
81 public void setMessageFactory(MessageFactory messageFactory) {
82 this.messageFactory = messageFactory;
83 }
84
85
86
87
88
89
90
91
92
93 public void setlangAttributeOnSoap11FaultString(boolean langAttributeOnSoap11FaultString) {
94 this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
95 }
96
97 public void setSoapVersion(SoapVersion version) {
98 if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
99 if (SoapVersion.SOAP_11 == version) {
100 messageFactoryProtocol = SOAPConstants.SOAP_1_1_PROTOCOL;
101 }
102 else if (SoapVersion.SOAP_12 == version) {
103 messageFactoryProtocol = SOAPConstants.SOAP_1_2_PROTOCOL;
104 }
105 else {
106 throw new IllegalArgumentException(
107 "Invalid version [" + version + "]. Expected the SOAP_11 or SOAP_12 constant");
108 }
109 }
110 else if (SoapVersion.SOAP_11 != version) {
111 throw new IllegalArgumentException("SAAJ 1.1 and 1.2 only support SOAP 1.1");
112 }
113 }
114
115 public void afterPropertiesSet() throws Exception {
116 if (messageFactory == null) {
117 try {
118 if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
119 if (!StringUtils.hasLength(messageFactoryProtocol)) {
120 messageFactoryProtocol = SOAPConstants.SOAP_1_1_PROTOCOL;
121 }
122 if (logger.isInfoEnabled()) {
123 logger.info("Creating SAAJ 1.3 MessageFactory with " + messageFactoryProtocol);
124 }
125 messageFactory = MessageFactory.newInstance(messageFactoryProtocol);
126 }
127 else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
128 logger.info("Creating SAAJ 1.2 MessageFactory");
129 messageFactory = MessageFactory.newInstance();
130 }
131 else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_11) {
132 logger.info("Creating SAAJ 1.1 MessageFactory");
133 messageFactory = MessageFactory.newInstance();
134 }
135 else {
136 throw new IllegalStateException(
137 "SaajSoapMessageFactory requires SAAJ 1.1, which was not found on the classpath");
138 }
139 }
140 catch (NoSuchMethodError ex) {
141 throw new SoapMessageCreationException(
142 "Could not create SAAJ MessageFactory. Is the version of the SAAJ specification interfaces [" +
143 SaajUtils.getSaajVersionString() +
144 "] the same as the version supported by the application server?", ex);
145 }
146 catch (SOAPException ex) {
147 throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex);
148 }
149 }
150 if (logger.isDebugEnabled()) {
151 logger.debug("Using MessageFactory class [" + messageFactory.getClass().getName() + "]");
152 }
153 }
154
155 public WebServiceMessage createWebServiceMessage() {
156 try {
157 return new SaajSoapMessage(messageFactory.createMessage(), langAttributeOnSoap11FaultString);
158 }
159 catch (SOAPException ex) {
160 throw new SoapMessageCreationException("Could not create empty message: " + ex.getMessage(), ex);
161 }
162 }
163
164 public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
165 MimeHeaders mimeHeaders = parseMimeHeaders(inputStream);
166 try {
167 inputStream = checkForUtf8ByteOrderMark(inputStream);
168 return new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, inputStream));
169 }
170 catch (SOAPException ex) {
171
172
173 String contentType = StringUtils
174 .arrayToCommaDelimitedString(mimeHeaders.getHeader(TransportConstants.HEADER_CONTENT_TYPE));
175 if (contentType.indexOf("startinfo") != -1) {
176 contentType = contentType.replace("startinfo", "start-info");
177 mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);
178 try {
179 return new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, inputStream),
180 langAttributeOnSoap11FaultString);
181 }
182 catch (SOAPException e) {
183
184 }
185 }
186 throw new SoapMessageCreationException("Could not create message from InputStream: " + ex.getMessage(), ex);
187 }
188 }
189
190 private MimeHeaders parseMimeHeaders(InputStream inputStream) throws IOException {
191 MimeHeaders mimeHeaders = new MimeHeaders();
192 if (inputStream instanceof TransportInputStream) {
193 TransportInputStream transportInputStream = (TransportInputStream) inputStream;
194 for (Iterator headerNames = transportInputStream.getHeaderNames(); headerNames.hasNext();) {
195 String headerName = (String) headerNames.next();
196 for (Iterator headerValues = transportInputStream.getHeaders(headerName); headerValues.hasNext();) {
197 String headerValue = (String) headerValues.next();
198 StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");
199 while (tokenizer.hasMoreTokens()) {
200 mimeHeaders.addHeader(headerName, tokenizer.nextToken().trim());
201 }
202 }
203 }
204 }
205 return mimeHeaders;
206 }
207
208
209
210
211
212
213
214 private InputStream checkForUtf8ByteOrderMark(InputStream inputStream) throws IOException {
215 PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3);
216 byte[] bom = new byte[3];
217 if (pushbackInputStream.read(bom) != -1) {
218
219 if (!(bom[0] == (byte) 0xEF && bom[1] == (byte) 0xBB && bom[2] == (byte) 0xBF)) {
220 pushbackInputStream.unread(bom);
221 }
222 }
223 return pushbackInputStream;
224 }
225
226 public String toString() {
227 StringBuffer buffer = new StringBuffer("SaajSoapMessageFactory[");
228 buffer.append(SaajUtils.getSaajVersionString());
229 if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
230 buffer.append(',');
231 buffer.append(messageFactoryProtocol);
232 }
233 buffer.append(']');
234 return buffer.toString();
235 }
236 }