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