View Javadoc

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