1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.monitor;
14
15 import java.io.ByteArrayInputStream;
16 import java.io.IOException;
17 import java.io.StringWriter;
18 import java.net.URL;
19 import java.util.Vector;
20
21 import org.apache.commons.httpclient.Header;
22 import org.apache.commons.httpclient.HttpParser;
23 import org.apache.ws.security.WSSecurityException;
24 import org.apache.xmlbeans.XmlObject;
25 import org.w3c.dom.Document;
26
27 import com.eviware.soapui.SoapUI;
28 import com.eviware.soapui.impl.wsdl.WsdlOperation;
29 import com.eviware.soapui.impl.wsdl.WsdlProject;
30 import com.eviware.soapui.impl.wsdl.submit.WsdlMessageExchange;
31 import com.eviware.soapui.impl.wsdl.submit.transports.http.MultipartMessageSupport;
32 import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
33 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
34 import com.eviware.soapui.impl.wsdl.support.wss.IncomingWss;
35 import com.eviware.soapui.model.ModelItem;
36 import com.eviware.soapui.model.iface.Attachment;
37 import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
38 import com.eviware.soapui.settings.WsdlSettings;
39 import com.eviware.soapui.support.Tools;
40 import com.eviware.soapui.support.types.StringToStringMap;
41 import com.eviware.soapui.support.xml.XmlUtils;
42
43 public class WsdlMonitorMessageExchange extends WsdlMessageExchange
44 {
45 private URL targetUrl;
46 private StringToStringMap responseHeaders;
47 private long timeTaken;
48 private long timestamp;
49 private StringToStringMap requestHeaders;
50 private String requestContent;
51 private String responseContent;
52 private int responseContentLength;
53 private int requestContentLength;
54 private String requestHost;
55 private WsdlProject project;
56 private WsdlOperation operation;
57 private byte[] capturedRequestData;
58 private byte[] capturedResponseData;
59 private String responseContentType;
60 private MultipartMessageSupport responseMmSupport;
61
62 private static final String HTTP_ELEMENT_CHARSET = "US-ASCII";
63 private SoapVersion soapVersion;
64 private MultipartMessageSupport requestMmSupport;
65 private String requestContentType;
66 private boolean discarded;
67 private Vector requestWssResult;
68 private Vector responseWssResult;
69
70 public WsdlMonitorMessageExchange( WsdlProject project )
71 {
72 this.project = project;
73 responseHeaders = new StringToStringMap();
74 requestHeaders = new StringToStringMap();
75 timestamp = System.currentTimeMillis();
76 }
77
78 @Override
79 public WsdlOperation getOperation()
80 {
81 return operation;
82 }
83
84 public Attachment[] getRequestAttachments()
85 {
86 return requestMmSupport == null ? new Attachment[0] : requestMmSupport.getAttachments();
87 }
88
89 public String getRequestContent()
90 {
91 return requestMmSupport == null ? requestContent : requestMmSupport.getContentAsString();
92 }
93
94 public StringToStringMap getRequestHeaders()
95 {
96 return requestHeaders;
97 }
98
99 public Attachment[] getResponseAttachments()
100 {
101 return responseMmSupport == null ? new Attachment[0] : responseMmSupport.getAttachments();
102 }
103
104 public String getResponseContent()
105 {
106 return responseMmSupport == null ? responseContent : responseMmSupport.getContentAsString();
107 }
108
109 public StringToStringMap getResponseHeaders()
110 {
111 return responseHeaders;
112 }
113
114 public long getTimeTaken()
115 {
116 return timeTaken;
117 }
118
119 public long getTimestamp()
120 {
121 return timestamp;
122 }
123
124 public void setTargetUrl( URL targetHost )
125 {
126 this.targetUrl = targetHost;
127 }
128
129 public boolean isActive()
130 {
131 return false;
132 }
133
134 public long getRequestContentLength()
135 {
136 return requestContentLength;
137 }
138
139 public long getResponseContentLength()
140 {
141 return responseContentLength;
142 }
143
144 public String getRequestHost()
145 {
146 return requestHost;
147 }
148
149 public URL getTargetUrl()
150 {
151 return targetUrl;
152 }
153
154 public byte[] getRawRequestData()
155 {
156 return capturedRequestData;
157 }
158
159 public byte[] getRawResponseData()
160 {
161 return capturedResponseData;
162 }
163
164 @Override
165 public boolean hasRawData()
166 {
167 return true;
168 }
169
170 public void finish( byte[] capturedRequestData, byte[] capturedResponseData )
171 {
172 this.capturedRequestData = capturedRequestData;
173 this.capturedResponseData = capturedResponseData;
174
175 if( timeTaken == 0 )
176 timeTaken = System.currentTimeMillis() - timestamp;
177 }
178
179 public void prepare( IncomingWss requestWss, IncomingWss responseWss )
180 {
181 parseRequestData( capturedRequestData, requestWss );
182 parseReponseData( capturedResponseData, responseWss );
183 }
184
185 private void parseReponseData( byte[] capturedResponseData, IncomingWss responseWss )
186 {
187 responseContentLength = capturedResponseData.length;
188 ByteArrayInputStream in = new ByteArrayInputStream( capturedResponseData );
189 try
190 {
191
192 String line = null;
193 do
194 {
195 line = HttpParser.readLine( in, HTTP_ELEMENT_CHARSET );
196 }
197 while( line != null && line.length() == 0 );
198
199 if( line == null )
200 {
201 throw new Exception( "Missing request status line" );
202 }
203
204 Header[] headers = HttpParser.parseHeaders( in, HTTP_ELEMENT_CHARSET );
205 if( headers != null )
206 {
207 for( Header header : headers )
208 {
209 responseHeaders.put( header.getName(), header.getValue() );
210 }
211 }
212
213 responseContentType = responseHeaders.get( "Content-Type" );
214 if( responseContentType != null && responseContentType.toUpperCase().startsWith( "MULTIPART" ))
215 {
216 StringToStringMap values = StringToStringMap.fromHttpHeader( responseContentType );
217 responseMmSupport = new MultipartMessageSupport(
218 new MonitorMessageExchangeDataSource( "monitor response", in, responseContentType ), values.get( "start" ), null, true,
219 SoapUI.getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES ));
220 responseContentType = responseMmSupport.getRootPart().getContentType();
221 }
222 else
223 {
224 this.responseContent = XmlUtils.prettyPrintXml( Tools.readAll( in, 0 ).toString());
225 }
226
227 if( responseWss != null )
228 {
229 Document dom = XmlUtils.parseXml( responseContent );
230 try
231 {
232 responseWssResult = responseWss.processIncoming( dom, new DefaultPropertyExpansionContext(project ) );
233 if( responseWssResult != null && responseWssResult.size() > 0 )
234 {
235 StringWriter writer = new StringWriter();
236 XmlUtils.serialize( dom, writer );
237 responseContent = writer.toString();
238 }
239 }
240 catch( Exception e )
241 {
242 if( responseWssResult != null )
243 responseWssResult = new Vector();
244 responseWssResult.add( e );
245 }
246 }
247 }
248 catch( Exception e )
249 {
250 try
251 {
252 in.close();
253 }
254 catch( IOException e1 )
255 {
256 e1.printStackTrace();
257 }
258 }
259 }
260
261 private void parseRequestData( byte[] capturedRequestData, IncomingWss requestWss )
262 {
263 requestContentLength = capturedRequestData.length;
264 ByteArrayInputStream in = new ByteArrayInputStream( capturedRequestData );
265 try
266 {
267
268 String line = null;
269 do
270 {
271 line = HttpParser.readLine( in, HTTP_ELEMENT_CHARSET );
272 }
273 while( line != null && line.length() == 0 );
274
275 if( line == null )
276 {
277 throw new Exception( "Missing request status line" );
278 }
279
280 Header[] headers = HttpParser.parseHeaders( in, HTTP_ELEMENT_CHARSET );
281 if( headers != null )
282 {
283 for( Header header : headers )
284 {
285 requestHeaders.put( header.getName(), header.getValue() );
286 }
287 }
288
289 requestContentType = requestHeaders.get( "Content-Type" );
290 if( requestContentType != null && requestContentType.toUpperCase().startsWith( "MULTIPART" ))
291 {
292 StringToStringMap values = StringToStringMap.fromHttpHeader( requestContentType );
293 requestMmSupport = new MultipartMessageSupport(
294 new MonitorMessageExchangeDataSource( "monitor request", in, requestContentType ), values.get( "start" ), null, true,
295 SoapUI.getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES ));
296 requestContentType = requestMmSupport.getRootPart().getContentType();
297 }
298 else
299 {
300 this.requestContent = XmlUtils.prettyPrintXml( Tools.readAll( in, 0 ).toString() );
301 }
302
303 if( requestWss != null )
304 {
305 Document dom = XmlUtils.parseXml( requestContent );
306 try
307 {
308 requestWssResult = requestWss.processIncoming( dom, new DefaultPropertyExpansionContext(project ) );
309 if( requestWssResult != null && requestWssResult.size() > 0 )
310 {
311 StringWriter writer = new StringWriter();
312 XmlUtils.serialize( dom, writer );
313 requestContent = writer.toString();
314 }
315 }
316 catch( Exception e )
317 {
318 if( requestWssResult != null )
319 requestWssResult = new Vector();
320 requestWssResult.add( e );
321 }
322 }
323
324 operation = findOperation();
325 }
326 catch( Exception e )
327 {
328 try
329 {
330 in.close();
331 }
332 catch( IOException e1 )
333 {
334 e1.printStackTrace();
335 }
336 }
337 }
338
339 private WsdlOperation findOperation() throws Exception
340 {
341 soapVersion = SoapUtils.initSoapVersion( requestContentType );
342 if( soapVersion == null )
343 throw new Exception( "Unrecognized SOAP Version" );
344
345 String soapAction = SoapUtils.getSoapAction( soapVersion, requestHeaders );
346
347 return SoapUtils.findOperationForRequest( soapVersion, soapAction,
348 XmlObject.Factory.parse( getRequestContent() ), project.getInterfaceList(), true );
349 }
350
351 public void setRequestHost( String requestHost )
352 {
353 this.requestHost = requestHost;
354 }
355
356 public SoapVersion getSoapVersion()
357 {
358 if( soapVersion == null )
359 soapVersion = SoapUtils.initSoapVersion( requestHeaders.get( "Content-Type" ) );
360
361 return soapVersion;
362 }
363
364 public void setTimeTaken( long timeTaken )
365 {
366 this.timeTaken = timeTaken;
367 }
368
369 public void discard()
370 {
371 operation = null;
372 project = null;
373
374 requestContent = null;
375 requestHeaders = null;
376
377 responseContent = null;
378 responseHeaders = null;
379
380 requestMmSupport = null;
381
382 discarded = true;
383 }
384
385 public ModelItem getModelItem()
386 {
387 return null;
388 }
389
390 public boolean isDiscarded()
391 {
392 return discarded;
393 }
394
395 public Vector getRequestWssResult()
396 {
397 return requestWssResult;
398 }
399
400 public Vector getResponseWssResult()
401 {
402 return responseWssResult;
403 }
404 }