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