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.submit.transports.http;
14  
15  import java.net.InetAddress;
16  import java.util.ArrayList;
17  import java.util.List;
18  
19  import org.apache.commons.httpclient.Header;
20  import org.apache.commons.httpclient.HostConfiguration;
21  import org.apache.commons.httpclient.HttpClient;
22  import org.apache.commons.httpclient.HttpMethodBase;
23  import org.apache.commons.httpclient.HttpState;
24  import org.apache.log4j.Logger;
25  
26  import com.eviware.soapui.SoapUI;
27  import com.eviware.soapui.impl.support.AbstractHttpRequestInterface;
28  import com.eviware.soapui.impl.support.http.HttpRequestInterface;
29  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
30  import com.eviware.soapui.impl.wsdl.WsdlProject;
31  import com.eviware.soapui.impl.wsdl.submit.RequestFilter;
32  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MimeMessageResponse;
33  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedDeleteMethod;
34  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod;
35  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedHeadMethod;
36  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedOptionsMethod;
37  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod;
38  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPutMethod;
39  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedTraceMethod;
40  import com.eviware.soapui.impl.wsdl.support.PathUtils;
41  import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
42  import com.eviware.soapui.impl.wsdl.support.http.SoapUIHostConfiguration;
43  import com.eviware.soapui.impl.wsdl.support.wss.WssCrypto;
44  import com.eviware.soapui.model.iface.Request;
45  import com.eviware.soapui.model.iface.Response;
46  import com.eviware.soapui.model.iface.SubmitContext;
47  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
48  import com.eviware.soapui.model.settings.Settings;
49  import com.eviware.soapui.model.support.ModelSupport;
50  import com.eviware.soapui.settings.HttpSettings;
51  import com.eviware.soapui.support.types.StringToStringMap;
52  
53  /***
54   * HTTP transport that uses HttpClient to send/receive SOAP messages
55   * 
56   * @author Ole.Matzura
57   */
58  
59  public class HttpClientRequestTransport implements BaseHttpRequestTransport
60  {
61  	private List<RequestFilter> filters = new ArrayList<RequestFilter>();
62  	private final static Logger log = Logger.getLogger( HttpClientRequestTransport.class );
63  
64  	public HttpClientRequestTransport()
65  	{
66  	}
67  
68  	public void addRequestFilter( RequestFilter filter )
69  	{
70  		filters.add( filter );
71  	}
72  
73  	public void removeRequestFilter( RequestFilter filter )
74  	{
75  		filters.remove( filter );
76  	}
77  
78  	public void abortRequest( SubmitContext submitContext )
79  	{
80  		HttpMethodBase postMethod = ( HttpMethodBase )submitContext.getProperty( HTTP_METHOD );
81  		if( postMethod != null )
82  			postMethod.abort();
83  	}
84  
85  	public Response sendRequest( SubmitContext submitContext, Request request ) throws Exception
86  	{
87  		AbstractHttpRequestInterface<?> httpRequest = ( AbstractHttpRequestInterface<?> )request;
88  
89  		HttpClient httpClient = HttpClientSupport.getHttpClient();
90  		ExtendedHttpMethod httpMethod = createHttpMethod( httpRequest );
91  		boolean createdState = false;
92  
93  		HttpState httpState = ( HttpState )submitContext.getProperty( SubmitContext.HTTP_STATE_PROPERTY );
94  		if( httpState == null )
95  		{
96  			httpState = new HttpState();
97  			submitContext.setProperty( SubmitContext.HTTP_STATE_PROPERTY, httpState );
98  			createdState = true;
99  		}
100 
101 		HostConfiguration hostConfiguration = new HostConfiguration();
102 
103 		String localAddress = System.getProperty( "soapui.bind.address", httpRequest.getBindAddress() );
104 		if( localAddress == null || localAddress.trim().length() == 0 )
105 			localAddress = SoapUI.getSettings().getString( HttpSettings.BIND_ADDRESS, null );
106 
107 		if( localAddress != null && localAddress.trim().length() > 0 )
108 		{
109 			try
110 			{
111 				hostConfiguration.setLocalAddress( InetAddress.getByName( localAddress ) );
112 			}
113 			catch( Exception e )
114 			{
115 				SoapUI.logError( e );
116 			}
117 		}
118 
119 		submitContext.removeProperty( RESPONSE );
120 		submitContext.setProperty( HTTP_METHOD, httpMethod );
121 		submitContext.setProperty( POST_METHOD, httpMethod );
122 		submitContext.setProperty( HTTP_CLIENT, httpClient );
123 		submitContext.setProperty( REQUEST_CONTENT, httpRequest.getRequestContent() );
124 		submitContext.setProperty( HOST_CONFIGURATION, hostConfiguration );
125 		submitContext.setProperty( WSDL_REQUEST, httpRequest );
126 		submitContext.setProperty( RESPONSE_PROPERTIES, new StringToStringMap() );
127 
128 		for( RequestFilter filter : filters )
129 		{
130 			filter.filterRequest( submitContext, httpRequest );
131 		}
132 
133 		try
134 		{
135 			Settings settings = httpRequest.getSettings();
136 
137 			// custom http headers last so they can be overridden
138 			StringToStringMap headers = httpRequest.getRequestHeaders();
139 			for( String header : headers.keySet() )
140 			{
141 				String headerValue = headers.get( header );
142 				headerValue = PropertyExpander.expandProperties( submitContext, headerValue );
143 				httpMethod.setRequestHeader( header, headerValue );
144 			}
145 
146 			// do request
147 			WsdlProject project = ( WsdlProject )ModelSupport.getModelItemProject( httpRequest );
148 			WssCrypto crypto = null;
149 			if( project != null )
150 			{
151 				crypto = project.getWssContainer().getCryptoByName(
152 						PropertyExpander.expandProperties( submitContext, httpRequest.getSslKeystore() ) );
153 			}
154 
155 			if( crypto != null && WssCrypto.STATUS_OK.equals( crypto.getStatus() ) )
156 			{
157 				hostConfiguration.getParams().setParameter( SoapUIHostConfiguration.SOAPUI_SSL_CONFIG,
158 						crypto.getSource() + " " + crypto.getPassword() );
159 			}
160 
161 			// dump file?
162 			httpMethod.setDumpFile( PathUtils.expandPath( httpRequest.getDumpFile(),
163 					( AbstractWsdlModelItem<?> )httpRequest, submitContext ) );
164 
165 			// include request time?
166 			if( settings.getBoolean( HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN ) )
167 				httpMethod.initStartTime();
168 
169 			// submit!
170 			httpClient.executeMethod( hostConfiguration, httpMethod, httpState );
171 			httpMethod.getTimeTaken();
172 		}
173 		catch( Throwable t )
174 		{
175 			httpMethod.setFailed( t );
176 
177 			if( t instanceof Exception )
178 				throw ( Exception )t;
179 
180 			SoapUI.logError( t );
181 			throw new Exception( t );
182 		}
183 		finally
184 		{
185 			for( int c = filters.size() - 1; c >= 0; c-- )
186 			{
187 				filters.get( c ).afterRequest( submitContext, httpRequest );
188 			}
189 
190 			if( !submitContext.hasProperty( RESPONSE ) )
191 			{
192 				createDefaultResponse( submitContext, httpRequest, httpMethod );
193 			}
194 
195 			Response response = ( Response )submitContext.getProperty( BaseHttpRequestTransport.RESPONSE );
196 			StringToStringMap responseProperties = ( StringToStringMap )submitContext
197 					.getProperty( BaseHttpRequestTransport.RESPONSE_PROPERTIES );
198 
199 			for( String key : responseProperties.keySet() )
200 			{
201 				response.setProperty( key, responseProperties.get( key ) );
202 			}
203 
204 			if( httpMethod != null )
205 			{
206 				httpMethod.releaseConnection();
207 			}
208 			else
209 				log.error( "PostMethod is null" );
210 
211 			if( createdState )
212 			{
213 				submitContext.setProperty( SubmitContext.HTTP_STATE_PROPERTY, null );
214 			}
215 		}
216 
217 		return ( Response )submitContext.getProperty( BaseHttpRequestTransport.RESPONSE );
218 	}
219 
220 	private void createDefaultResponse( SubmitContext submitContext, AbstractHttpRequestInterface<?> httpRequest,
221 			ExtendedHttpMethod httpMethod )
222 	{
223 		String requestContent = ( String )submitContext.getProperty( BaseHttpRequestTransport.REQUEST_CONTENT );
224 
225 		// check content-type for multiplart
226 		Header responseContentTypeHeader = httpMethod.getResponseHeader( "Content-Type" );
227 		Response response = null;
228 
229 		if( responseContentTypeHeader != null
230 				&& responseContentTypeHeader.getValue().toUpperCase().startsWith( "MULTIPART" ) )
231 		{
232 			response = new MimeMessageResponse( httpRequest, httpMethod, requestContent, submitContext );
233 		}
234 		else
235 		{
236 			response = new SinglePartHttpResponse( httpRequest, httpMethod, requestContent, submitContext );
237 		}
238 
239 		submitContext.setProperty( BaseHttpRequestTransport.RESPONSE, response );
240 	}
241 
242 	private ExtendedHttpMethod createHttpMethod( AbstractHttpRequestInterface<?> httpRequest )
243 	{
244 		if( httpRequest instanceof HttpRequestInterface<?> )
245 		{
246 			HttpRequestInterface<?> restRequest = ( HttpRequestInterface<?> )httpRequest;
247 			switch( restRequest.getMethod() )
248 			{
249 			case GET :
250 				return new ExtendedGetMethod();
251 			case HEAD :
252 				return new ExtendedHeadMethod();
253 			case DELETE :
254 				return new ExtendedDeleteMethod();
255 			case PUT :
256 				return new ExtendedPutMethod();
257 			case OPTIONS :
258 				return new ExtendedOptionsMethod();
259 			case TRACE :
260 				return new ExtendedTraceMethod();
261 			}
262 		}
263 
264 		ExtendedPostMethod extendedPostMethod = new ExtendedPostMethod();
265 
266 		extendedPostMethod.setAfterRequestInjection( httpRequest.getAfterRequestInjection() );
267 		return extendedPostMethod;
268 	}
269 
270 }