View Javadoc

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