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.mock;
14  
15  import java.io.ByteArrayOutputStream;
16  import java.io.IOException;
17  import java.io.StringWriter;
18  import java.util.Enumeration;
19  import java.util.Vector;
20  
21  import javax.mail.MessagingException;
22  import javax.servlet.ServletInputStream;
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  
26  import org.apache.xmlbeans.XmlException;
27  import org.apache.xmlbeans.XmlObject;
28  import org.w3c.dom.Document;
29  
30  import com.eviware.soapui.SoapUI;
31  import com.eviware.soapui.impl.wsdl.WsdlOperation;
32  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MockRequestDataSource;
33  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MultipartMessageSupport;
34  import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
35  import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
36  import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
37  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
38  import com.eviware.soapui.impl.wsdl.support.wss.IncomingWss;
39  import com.eviware.soapui.model.iface.Attachment;
40  import com.eviware.soapui.model.mock.MockRequest;
41  import com.eviware.soapui.settings.WsdlSettings;
42  import com.eviware.soapui.support.StringUtils;
43  import com.eviware.soapui.support.Tools;
44  import com.eviware.soapui.support.types.StringToStringMap;
45  import com.eviware.soapui.support.types.StringToStringsMap;
46  import com.eviware.soapui.support.xml.XmlUtils;
47  
48  /***
49   * Request-class created when receiving an external request to a WsdlMockService
50   * 
51   * @author ole.matzura
52   */
53  
54  public class WsdlMockRequest implements MockRequest
55  {
56  	private StringToStringsMap requestHeaders;
57  	private String requestContent;
58  	private MultipartMessageSupport mmSupport;
59  	private XmlObject requestXmlObject;
60  	private SoapVersion soapVersion;
61  	private final HttpServletResponse response;
62  	private String protocol;
63  	private String path;
64  	private String soapAction;
65  	private final WsdlMockRunContext context;
66  	private final WsdlMockRunContext requestContext;
67  	private final HttpServletRequest request;
68  	private Vector<Object> wssResult;
69  	private MockRequestDataSource mockRequestDataSource;
70  	private String actualRequestContent;
71  	private boolean responseMessage;
72  	private String method;
73  
74  	public WsdlMockRequest( HttpServletRequest request, HttpServletResponse response, WsdlMockRunContext context )
75  			throws Exception
76  	{
77  		this.request = request;
78  		this.response = response;
79  		this.context = context;
80  
81  		requestContext = new WsdlMockRunContext( context.getMockService(), null );
82  
83  		requestHeaders = new StringToStringsMap();
84  		for( Enumeration<?> e = request.getHeaderNames(); e.hasMoreElements(); )
85  		{
86  			String header = ( String )e.nextElement();
87  			String lcHeader = header.toLowerCase();
88  			if( lcHeader.equals( "soapaction" ) )
89  				requestHeaders.put( "SOAPAction", request.getHeader( header ) );
90  			else if( lcHeader.equals( "content-type" ) )
91  				requestHeaders.put( "Content-Type", request.getHeader( header ) );
92  			else if( lcHeader.equals( "content-length" ) )
93  				requestHeaders.put( "Content-Length", request.getHeader( header ) );
94  			else if( lcHeader.equals( "content-encoding" ) )
95  				requestHeaders.put( "Content-Encoding", request.getHeader( header ) );
96  			else
97  				requestHeaders.put( header, request.getHeader( header ) );
98  		}
99  
100 		protocol = request.getProtocol();
101 		path = request.getPathInfo();
102 		if( path == null )
103 			path = "";
104 
105 		if( request.getMethod().equals( "POST" ) )
106 		{
107 			initPostRequest( request, context );
108 		}
109 	}
110 
111 	protected void initPostRequest( HttpServletRequest request, WsdlMockRunContext context ) throws Exception
112 	{
113 		String contentType = request.getContentType();
114 
115 		if( contentType != null && contentType.toUpperCase().startsWith( "MULTIPART" ) )
116 		{
117 			readMultipartRequest( request );
118 			if( mmSupport != null && mmSupport.getRootPart() != null )
119 				contentType = mmSupport.getRootPart().getContentType();
120 		}
121 		else
122 		{
123 			this.requestContent = readRequestContent( request );
124 
125 			if( StringUtils.hasContent( context.getMockService().getIncomingWss() ) )
126 			{
127 				IncomingWss incoming = context.getMockService().getProject().getWssContainer()
128 						.getIncomingWssByName( context.getMockService().getIncomingWss() );
129 				if( incoming != null )
130 				{
131 					Document dom = XmlUtils.parseXml( requestContent );
132 					try
133 					{
134 						wssResult = incoming.processIncoming( dom, context );
135 						if( wssResult != null && wssResult.size() > 0 )
136 						{
137 							StringWriter writer = new StringWriter();
138 							XmlUtils.serialize( dom, writer );
139 							actualRequestContent = requestContent;
140 							requestContent = writer.toString();
141 						}
142 					}
143 					catch( Exception e )
144 					{
145 						if( wssResult == null )
146 							wssResult = new Vector<Object>();
147 						wssResult.add( e );
148 					}
149 				}
150 			}
151 		}
152 
153 		try
154 		{
155 			soapVersion = SoapUtils.deduceSoapVersion( contentType, getRequestXmlObject() );
156 		}
157 		catch( Exception e )
158 		{
159 			// ignore non xml requests
160 		}
161 
162 		if( soapVersion == null )
163 			soapVersion = SoapVersion.Soap11;
164 
165 		soapAction = SoapUtils.getSoapAction( soapVersion, requestHeaders );
166 	}
167 
168 	public SoapVersion getSoapVersion()
169 	{
170 		return soapVersion;
171 	}
172 
173 	public String getProtocol()
174 	{
175 		return protocol;
176 	}
177 
178 	public Vector<?> getWssResult()
179 	{
180 		return wssResult;
181 	}
182 
183 	private void readMultipartRequest( HttpServletRequest request ) throws MessagingException
184 	{
185 		StringToStringMap values = StringToStringMap.fromHttpHeader( request.getContentType() );
186 		mockRequestDataSource = new MockRequestDataSource( request );
187 		mmSupport = new MultipartMessageSupport( mockRequestDataSource, values.get( "start" ), null, true, requestContext
188 				.getMockService().getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES ) );
189 	}
190 
191 	private String readRequestContent( HttpServletRequest request ) throws Exception
192 	{
193 		String messageContent = null;
194 		String encoding = request.getCharacterEncoding();
195 		if( encoding != null )
196 			encoding = StringUtils.unquote( encoding );
197 
198 		ServletInputStream is = request.getInputStream();
199 		if( is.markSupported() && request.getContentLength() > 0 )
200 			is.mark( request.getContentLength() );
201 
202 		ByteArrayOutputStream out = Tools.readAll( is, Tools.READ_ALL );
203 		byte[] data = out.toByteArray();
204 
205 		if( is.markSupported() && request.getContentLength() > 0 )
206 		{
207 			try
208 			{
209 				is.reset();
210 			}
211 			catch( IOException e )
212 			{
213 				SoapUI.logError( e );
214 			}
215 		}
216 
217 		// decompress
218 		String compressionAlg = HttpClientSupport.getCompressionType( request.getContentType(),
219 				requestHeaders.get( "Content-Encoding", ( String )null ) );
220 
221 		if( compressionAlg != null )
222 		{
223 			try
224 			{
225 				data = CompressionSupport.decompress( compressionAlg, data );
226 			}
227 			catch( Exception e )
228 			{
229 				IOException ioe = new IOException( "Decompression of response failed" );
230 				ioe.initCause( e );
231 				throw ioe;
232 			}
233 		}
234 
235 		int contentOffset = 0;
236 
237 		String contentType = request.getContentType();
238 		if( contentType != null && data.length > 0 )
239 		{
240 			if( contentType.toLowerCase().endsWith( "xml" ) )
241 			{
242 				if( data.length > 3 && data[0] == ( byte )239 && data[1] == ( byte )187 && data[2] == ( byte )191 )
243 				{
244 					encoding = "UTF-8";
245 					contentOffset = 3;
246 				}
247 			}
248 
249 			encoding = StringUtils.unquote( encoding );
250 
251 			messageContent = encoding == null ? new String( data ) : new String( data, contentOffset,
252 					( int )( data.length - contentOffset ), encoding );
253 		}
254 
255 		if( encoding == null )
256 			encoding = "UTF-8";
257 
258 		if( messageContent == null )
259 		{
260 			messageContent = new String( data, encoding );
261 		}
262 
263 		return messageContent;
264 	}
265 
266 	public Attachment[] getRequestAttachments()
267 	{
268 		return mmSupport == null ? new Attachment[0] : mmSupport.getAttachments();
269 	}
270 
271 	public String getRequestContent()
272 	{
273 		return mmSupport == null ? requestContent : mmSupport.getContentAsString();
274 	}
275 
276 	public StringToStringsMap getRequestHeaders()
277 	{
278 		return requestHeaders;
279 	}
280 
281 	public void setRequestContent( String requestContent )
282 	{
283 		this.requestContent = requestContent;
284 		requestXmlObject = null;
285 
286 		try
287 		{
288 			soapVersion = SoapUtils.deduceSoapVersion( request.getContentType(), getRequestXmlObject() );
289 		}
290 		catch( XmlException e )
291 		{
292 			SoapUI.logError( e );
293 		}
294 
295 		if( soapVersion == null )
296 			soapVersion = SoapVersion.Soap11;
297 	}
298 
299 	public XmlObject getRequestXmlObject() throws XmlException
300 	{
301 		if( requestXmlObject == null && StringUtils.hasContent( getRequestContent() ) )
302 			requestXmlObject = XmlObject.Factory.parse( getRequestContent() );
303 
304 		return requestXmlObject;
305 	}
306 
307 	public HttpServletResponse getHttpResponse()
308 	{
309 		return response;
310 	}
311 
312 	public HttpServletRequest getHttpRequest()
313 	{
314 		return request;
315 	}
316 
317 	public String getMethod()
318 	{
319 		return method == null ? request.getMethod() : method;
320 	}
321 
322 	public void setMethod( String method )
323 	{
324 		this.method = method;
325 	}
326 
327 	public XmlObject getContentElement() throws XmlException
328 	{
329 		return SoapUtils.getContentElement( getRequestXmlObject(), soapVersion );
330 	}
331 
332 	public String getPath()
333 	{
334 		return path;
335 	}
336 
337 	public WsdlMockRunContext getContext()
338 	{
339 		return context;
340 	}
341 
342 	public void setOperation( WsdlOperation operation )
343 	{
344 		if( mmSupport != null )
345 			mmSupport.setOperation( operation );
346 	}
347 
348 	public WsdlMockRunContext getRequestContext()
349 	{
350 		return requestContext;
351 	}
352 
353 	public String getSoapAction()
354 	{
355 		return soapAction;
356 	}
357 
358 	public void setSoapAction( String soapAction )
359 	{
360 		this.soapAction = soapAction;
361 	}
362 
363 	public byte[] getRawRequestData()
364 	{
365 		return mockRequestDataSource == null ? actualRequestContent == null ? requestContent.getBytes()
366 				: actualRequestContent.getBytes() : mockRequestDataSource.getData();
367 	}
368 
369 	public void setResponseMessage( boolean responseMessage )
370 	{
371 		this.responseMessage = responseMessage;
372 	}
373 
374 	public boolean isResponseMessage()
375 	{
376 		return responseMessage;
377 	}
378 }