View Javadoc

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