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