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