View Javadoc

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