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.MalformedURLException;
19  import java.net.URL;
20  import java.util.ArrayList;
21  import java.util.Enumeration;
22  import java.util.List;
23  import java.util.Vector;
24  
25  import javax.servlet.http.HttpServletRequest;
26  
27  import org.apache.commons.httpclient.Header;
28  import org.apache.commons.httpclient.HttpMethodBase;
29  import org.apache.xmlbeans.XmlObject;
30  import org.w3c.dom.Document;
31  
32  import com.eviware.soapui.SoapUI;
33  import com.eviware.soapui.impl.wsdl.WsdlInterface;
34  import com.eviware.soapui.impl.wsdl.WsdlOperation;
35  import com.eviware.soapui.impl.wsdl.WsdlProject;
36  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MultipartMessageSupport;
37  import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
38  import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
39  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
40  import com.eviware.soapui.impl.wsdl.support.wss.IncomingWss;
41  import com.eviware.soapui.model.iface.Attachment;
42  import com.eviware.soapui.model.iface.Operation;
43  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
44  import com.eviware.soapui.model.support.ModelSupport;
45  import com.eviware.soapui.support.Tools;
46  import com.eviware.soapui.support.types.StringToStringMap;
47  import com.eviware.soapui.support.xml.XmlUtils;
48  
49  public class JProxyServletWsdlMonitorMessageExchange extends WsdlMonitorMessageExchange
50  {
51  
52  	private WsdlOperation operation;
53  	private WsdlProject project;
54  	private String requestContent;
55  	private StringToStringMap requestHeaders;
56  	private String responseContent;
57  	private StringToStringMap responseHeaders;
58  	private MultipartMessageSupport requestMmSupport;
59  	private boolean discarded;
60  	private long timestampStart;
61  	private byte[] request;
62  	private byte[] response;
63  	private String requestHost;
64  	private URL targetURL;
65  	private String requestContentType;
66  	private Vector<Object> requestWssResult;
67  	private SoapVersion soapVersion;
68  	private String responseContentType;
69  	private MultipartMessageSupport responseMmSupport;
70  	private Vector<Object> responseWssResult;
71  	private long timestampEnd;
72  	private boolean capture;
73  	private byte[] requestRaw = null;
74  	private byte[] responseRaw = null;
75  
76  	public JProxyServletWsdlMonitorMessageExchange( WsdlProject project )
77  	{
78  		super( null );
79  		responseHeaders = new StringToStringMap();
80  		requestHeaders = new StringToStringMap();
81  		timestampStart = System.currentTimeMillis();
82  		this.project = project;
83  		capture = true;
84  	}
85  
86  	@Override
87  	public void discard()
88  	{
89  		operation = null;
90  		project = null;
91  
92  		requestContent = null;
93  		requestHeaders = null;
94  
95  		responseContent = null;
96  		responseHeaders = null;
97  
98  		requestMmSupport = null;
99  
100 		response = null;
101 		request = null;
102 		capture = false;
103 
104 		discarded = true;
105 	}
106 
107 	@Override
108 	public long getRequestContentLength()
109 	{
110 		return request == null ? -1 : request.length;
111 	}
112 
113 	@Override
114 	public String getRequestHost()
115 	{
116 		return requestHost;
117 	}
118 
119 	@Override
120 	public long getResponseContentLength()
121 	{
122 		return response == null ? -1 : response.length;
123 	}
124 
125 	@Override
126 	public URL getTargetUrl()
127 	{
128 		return this.targetURL;
129 	}
130 
131 	@Override
132 	public void prepare( IncomingWss incomingRequestWss, IncomingWss incomingResponseWss )
133 	{
134 		parseRequestData( incomingRequestWss );
135 		parseReponseData( incomingResponseWss );
136 	}
137 
138 	private void parseReponseData( IncomingWss incomingResponseWss )
139 	{
140 		ByteArrayInputStream in = new ByteArrayInputStream( response == null ? new byte[0] : response );
141 		try
142 		{
143 			responseContentType = responseHeaders.get( "Content-Type" );
144 			if( responseContentType != null && responseContentType.toUpperCase().startsWith( "MULTIPART" ) )
145 			{
146 				StringToStringMap values = StringToStringMap.fromHttpHeader( responseContentType );
147 				responseMmSupport = new MultipartMessageSupport( new MonitorMessageExchangeDataSource( "monitor response",
148 						in, responseContentType ), values.get( "start" ), null, true, false );
149 				responseContentType = responseMmSupport.getRootPart().getContentType();
150 			}
151 			else
152 			{
153 				String charset = getCharset( responseHeaders );
154 				this.responseContent = charset == null ? Tools.readAll( in, 0 ).toString() : Tools.readAll( in, 0 )
155 						.toString( charset );
156 			}
157 
158 			processResponseWss( incomingResponseWss );
159 		}
160 		catch( Exception e )
161 		{
162 			SoapUI.logError( e );
163 		}
164 		finally
165 		{
166 			try
167 			{
168 				in.close();
169 			}
170 			catch( IOException e1 )
171 			{
172 				SoapUI.logError( e1 );
173 			}
174 		}
175 	}
176 
177 	private void processResponseWss( IncomingWss incomingResponseWss ) throws IOException
178 	{
179 		if( incomingResponseWss != null )
180 		{
181 			Document dom = XmlUtils.parseXml( responseContent );
182 			try
183 			{
184 				responseWssResult = incomingResponseWss
185 						.processIncoming( dom, new DefaultPropertyExpansionContext( project ) );
186 				if( responseWssResult != null && responseWssResult.size() > 0 )
187 				{
188 					StringWriter writer = new StringWriter();
189 					XmlUtils.serialize( dom, writer );
190 					responseContent = writer.toString();
191 				}
192 			}
193 			catch( Exception e )
194 			{
195 				if( responseWssResult == null )
196 					responseWssResult = new Vector<Object>();
197 				responseWssResult.add( e );
198 			}
199 		}
200 
201 	}
202 
203 	private void parseRequestData( IncomingWss incomingRequestWss )
204 	{
205 		ByteArrayInputStream in = request == null ? new ByteArrayInputStream( new byte[0] ) : new ByteArrayInputStream(
206 				request );
207 		try
208 		{
209 
210 			requestContentType = requestHeaders.get( "Content-Type" );
211 			if( requestContentType != null && requestContentType.toUpperCase().startsWith( "MULTIPART" ) )
212 			{
213 				StringToStringMap values = StringToStringMap.fromHttpHeader( requestContentType );
214 				requestMmSupport = new MultipartMessageSupport( new MonitorMessageExchangeDataSource( "monitor request",
215 						in, requestContentType ), values.get( "start" ), null, true, false );
216 				requestContentType = requestMmSupport.getRootPart().getContentType();
217 			}
218 			else
219 			{
220 				String charset = getCharset( requestHeaders );
221 				this.requestContent = charset == null ? Tools.readAll( in, 0 ).toString() : Tools.readAll( in, 0 )
222 						.toString( charset );
223 			}
224 
225 			processRequestWss( incomingRequestWss );
226 
227 			operation = findOperation();
228 		}
229 		catch( Exception e )
230 		{
231 			SoapUI.logError( e );
232 		}
233 		finally
234 		{
235 			try
236 			{
237 				in.close();
238 			}
239 			catch( IOException e1 )
240 			{
241 				SoapUI.logError( e1 );
242 			}
243 		}
244 			}
245 
246 	private static String getCharset( StringToStringMap headers )
247 	{
248 		String requestContentType = headers.get( "Content-Type" );
249 		if( requestContentType != null )
250 		{
251 			StringToStringMap values = StringToStringMap.fromHttpHeader( requestContentType );
252 			if( values.containsKey( "charset" ) )
253 				return values.get( "charset" );
254 		}
255 
256 		String contentEncodingHeader = headers.get( "Content-Encoding" );
257 		if( contentEncodingHeader != null )
258 		{
259 			try
260 			{
261 				if( CompressionSupport.getAvailableAlgorithm( contentEncodingHeader ) == null )
262 				{
263 					new String( "" ).getBytes( contentEncodingHeader );
264 					return contentEncodingHeader;
265 				}
266 			}
267 			catch( Exception e )
268 			{
269 			}
270 		}
271 
272 		return null;
273 	}
274 
275 	private WsdlOperation findOperation() throws Exception
276 	{
277 		soapVersion = SoapUtils.deduceSoapVersion( requestContentType, XmlObject.Factory.parse( getRequestContent() ) );
278 		if( soapVersion == null )
279 			throw new Exception( "Unrecognized SOAP Version" );
280 
281 		String soapAction = SoapUtils.getSoapAction( soapVersion, requestHeaders );
282 
283 		List<WsdlOperation> operations = new ArrayList<WsdlOperation>();
284 		for( WsdlInterface iface : ModelSupport.getChildren( project, WsdlInterface.class ) )
285 		{
286 			for( Operation operation : iface.getOperationList() )
287 				operations.add( ( WsdlOperation )operation );
288 		}
289 
290 		return SoapUtils.findOperationForRequest( soapVersion, soapAction,
291 				XmlObject.Factory.parse( getRequestContent() ), operations, true, false, getRequestAttachments() );
292 	}
293 
294 	private void processRequestWss( IncomingWss incomingRequestWss ) throws IOException
295 	{
296 
297 		if( incomingRequestWss != null )
298 		{
299 			Document dom = XmlUtils.parseXml( requestContent );
300 			try
301 			{
302 				requestWssResult = incomingRequestWss.processIncoming( dom, new DefaultPropertyExpansionContext( project ) );
303 				if( requestWssResult != null && requestWssResult.size() > 0 )
304 				{
305 					StringWriter writer = new StringWriter();
306 					XmlUtils.serialize( dom, writer );
307 					requestContent = writer.toString();
308 				}
309 			}
310 			catch( Exception e )
311 			{
312 				if( requestWssResult == null )
313 					requestWssResult = new Vector<Object>();
314 				requestWssResult.add( e );
315 			}
316 		}
317 
318 	}
319 
320 	public WsdlOperation getOperation()
321 	{
322 		return operation;
323 	}
324 
325 	public Vector<?> getRequestWssResult()
326 	{
327 		return requestWssResult;
328 	}
329 
330 	public Vector<?> getResponseWssResult()
331 	{
332 		return responseWssResult;
333 	}
334 
335 	public Attachment[] getRequestAttachments()
336 	{
337 		return requestMmSupport == null ? new Attachment[0] : requestMmSupport.getAttachments();
338 	}
339 
340 	public String getRequestContent()
341 	{
342 		return requestMmSupport == null ? requestContent : requestMmSupport.getContentAsString();
343 	}
344 
345 	public byte[] getRawRequestData()
346 	{
347 		if( requestRaw != null )
348 			return requestRaw;
349 		else
350 			return request;
351 	}
352 
353 	public void setRawRequestData( byte[] data )
354 	{
355 		requestRaw = data;
356 	}
357 
358 	public byte[] getRawResponseData()
359 	{
360 		if( responseRaw == null )
361 			return response;
362 		else
363 			return responseRaw;
364 	}
365 
366 	public void setRawResponseData( byte[] data )
367 	{
368 		responseRaw = data;
369 	}
370 
371 	public StringToStringMap getRequestHeaders()
372 	{
373 		return requestHeaders;
374 	}
375 
376 	public Attachment[] getResponseAttachments()
377 	{
378 		return requestMmSupport == null ? new Attachment[0] : requestMmSupport.getAttachments();
379 	}
380 
381 	public String getResponseContent()
382 	{
383 		return responseContent;
384 	}
385 
386 	public StringToStringMap getResponseHeaders()
387 	{
388 		return responseHeaders;
389 	}
390 
391 	public long getTimeTaken()
392 	{
393 		return timestampEnd - timestampStart;
394 	}
395 
396 	public long getTimestamp()
397 	{
398 		return timestampStart;
399 	}
400 
401 	public boolean isDiscarded()
402 	{
403 		return discarded;
404 	}
405 
406 	public void stopCapture()
407 	{
408 		timestampEnd = System.currentTimeMillis();
409 		capture = false;
410 	}
411 
412 	public boolean isStopCapture()
413 	{
414 		return capture;
415 	}
416 
417 	public void setRequest( byte[] request )
418 	{
419 		this.request = request;
420 	}
421 
422 	public byte [] getRawResponseBody()
423 	{
424 		return response;
425 	}
426 	
427 	public void setRawResponseBody( byte[] response )
428 	{
429 		if( this.response == null )
430 		{
431 			this.response = response;
432 		}
433 		else
434 		{
435 			byte[] newResponse = new byte[this.response.length + response.length];
436 			for( int i = 0; i < this.response.length; i++ )
437 			{
438 				newResponse[i] = this.response[i];
439 			}
440 			for( int i = this.response.length; i < newResponse.length; i++ )
441 			{
442 				newResponse[i] = response[i - this.response.length];
443 			}
444 			this.response = newResponse;
445 		}
446 	}
447 
448 	public void setResponseHeader( String name, String value )
449 	{
450 		responseHeaders.put( name, value );
451 	}
452 
453 	public void setRequestHost( String serverName )
454 	{
455 		requestHost = serverName;
456 	}
457 
458 	public void setTargetHost( String remoteHost )
459 	{
460 	}
461 
462 	@SuppressWarnings( "unchecked" )
463 	public void setRequestHeader( HttpServletRequest httpRequest )
464 	{
465 		Enumeration<String> headerNames = httpRequest.getHeaderNames();
466 		while( headerNames.hasMoreElements() )
467 		{
468 			String name = headerNames.nextElement();
469 			Enumeration<String> header = httpRequest.getHeaders( name );
470 			while( header.hasMoreElements() )
471 			{
472 				String value = header.nextElement();
473 				if( value != null )
474 				{
475 					requestHeaders.put( name, value );
476 				}
477 			}
478 		}
479 	}
480 
481 	public void setTargetURL( String url )
482 	{
483 		try
484 		{
485 			this.targetURL = new URL( url );
486 		}
487 		catch( MalformedURLException e )
488 		{
489 			e.printStackTrace();
490 		}
491 	}
492 
493 	public int getResponseStatusCode()
494 	{
495 		return 0;
496 	}
497 
498 	public String getResponseContentType()
499 	{
500 		return null;
501 	}
502 
503 	public void setResponseHeader( HttpMethodBase method )
504 	{
505 		Header[] headers = method.getResponseHeaders();
506 		for( Header header : headers )
507 		{
508 			String name = header.getName();
509 			String value = header.getValue();
510 			if( value != null )
511 			{
512 				responseHeaders.put( name, value );
513 			}
514 		}
515 	}
516 
517 }