View Javadoc

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