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