View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 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 javax.activation.DataHandler;
    20  import javax.mail.MessagingException;
    21  import javax.mail.internet.MimeBodyPart;
    22  import javax.mail.internet.MimeMessage;
    23  import javax.mail.internet.MimeMultipart;
    24  import javax.mail.internet.PreencodedMimeBodyPart;
    25
    26  import org.apache.commons.httpclient.Header;
    27  import org.apache.commons.httpclient.HostConfiguration;
    28  import org.apache.commons.httpclient.HttpClient;
    29  import org.apache.commons.httpclient.HttpState;
    30  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
    31  import org.apache.log4j.Logger;
    32
    33  import com.eviware.soapui.SoapUI;
    34  import com.eviware.soapui.impl.wsdl.WsdlOperation;
    35  import com.eviware.soapui.impl.wsdl.WsdlRequest;
    36  import com.eviware.soapui.impl.wsdl.submit.RequestFilter;
    37  import com.eviware.soapui.impl.wsdl.submit.filters.PropertyExpansionRequestFilter;
    38  import com.eviware.soapui.impl.wsdl.support.MessageXmlObject;
    39  import com.eviware.soapui.impl.wsdl.support.MessageXmlPart;
    40  import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
    41  import com.eviware.soapui.model.iface.Response;
    42  import com.eviware.soapui.model.iface.SubmitContext;
    43  import com.eviware.soapui.model.settings.Settings;
    44  import com.eviware.soapui.settings.HttpSettings;
    45  import com.eviware.soapui.support.StringUtils;
    46  import com.eviware.soapui.support.types.StringToStringMap;
    47
    48  /***
    49   * HTTP transport that uses HttpClient to send/receive SOAP messages
    50   *
    51   * @author Ole.Matzura
    52   */
    53
    54  public class HttpClientRequestTransport implements BaseHttpRequestTransport
    55  {
    56  	private List<RequestFilter> filters = new ArrayList<RequestFilter>();
    57  	private final static Logger log = Logger.getLogger(HttpClientRequestTransport.class);
    58
    59  	public void addRequestFilter(RequestFilter filter)
    60  	{
    61  		filters.add( filter );
    62  	}
    63
    64  	public void removeRequestFilter(RequestFilter filter)
    65  	{
    66  		filters.remove( filter );
    67  	}
    68
    69  	public void abortRequest( SubmitContext submitContext )
    70  	{
    71  		TimeablePostMethod postMethod = (TimeablePostMethod) submitContext.getProperty( POST_METHOD );
    72  		postMethod.abort();
    73  	}
    74
    75  	public Response sendRequest( SubmitContext submitContext, WsdlRequest wsdlRequest ) throws Exception
    76  	{
    77  		HttpClient httpClient = HttpClientSupport.getHttpClient();
    78  		TimeablePostMethod postMethod = new TimeablePostMethod();
    79  		boolean createdState = false;
    80
    81  		HttpState httpState = (HttpState) submitContext.getProperty(SubmitContext.HTTP_STATE_PROPERTY);
    82  		if( httpState == null )
    83  		{
    84  		   httpState = new HttpState();
    85  		   submitContext.setProperty( SubmitContext.HTTP_STATE_PROPERTY, httpState );
    86  		   createdState = true;
    87  		}
    88
    89  		HostConfiguration hostConfiguration = new HostConfiguration();
    90
    91  		String localAddress = System.getProperty( "soapui.bind.address", wsdlRequest.getBindAddress() );
    92  		if( localAddress == null || localAddress.trim().length() == 0 )
    93  			localAddress = SoapUI.getSettings().getString( HttpSettings.BIND_ADDRESS, null );
    94
    95  		if( localAddress != null && localAddress.trim().length() > 0 )
    96  		{
    97  			try
    98  			{
    99  				hostConfiguration.setLocalAddress( InetAddress.getByName( localAddress ));
    100 			}
    101 			catch( Exception e )
    102 			{
    103 				SoapUI.logError( e );
    104 			}
    105 		}
    106
    107 		submitContext.setProperty( POST_METHOD, postMethod );
    108 		submitContext.setProperty( HTTP_CLIENT, httpClient );
    109 		submitContext.setProperty( REQUEST_CONTENT, wsdlRequest.getRequestContent() );
    110 		submitContext.setProperty( HOST_CONFIGURATION, hostConfiguration );
    111 		submitContext.setProperty( WSDL_REQUEST, wsdlRequest );
    112
    113 		for( RequestFilter filter : filters )
    114 		{
    115 			filter.filterRequest( submitContext, wsdlRequest );
    116 		}
    117
    118 		try
    119 		{
    120 			Settings settings = wsdlRequest.getSettings();
    121
    122 			// get request content
    123 			String requestContent = (String) submitContext.getProperty(REQUEST_CONTENT);
    124
    125 			// init
    126 			requestContent = initRequest(wsdlRequest, postMethod, requestContent);
    127
    128 			// include request time?
    129 			if (settings.getBoolean(HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN))
    130 				postMethod.initStartTime();
    131
    132 			//	custom http headers last so they can be overridden
    133 			StringToStringMap headers = wsdlRequest.getRequestHeaders();
    134 			for( String header : headers.keySet() )
    135 			{
    136 				String headerValue = headers.get( header );
    137 				headerValue = PropertyExpansionRequestFilter.expandProperties( submitContext, headerValue );
    138 				postMethod.setRequestHeader( header, headerValue );
    139 			}
    140
    141 			//	do request
    142 			httpClient.executeMethod(hostConfiguration, postMethod, httpState);
    143
    144 			Header responseContentTypeHeader = postMethod.getResponseHeader( "Content-Type" );
    145
    146 			if( !settings.getBoolean( WsdlRequest.INLINE_RESPONSE_ATTACHMENTS ) &&
    147 				 responseContentTypeHeader != null &&
    148 				 responseContentTypeHeader.getValue().toUpperCase().startsWith( "MULTIPART" ))
    149 			{
    150 				return new MimeMessageResponse( wsdlRequest, postMethod, requestContent );
    151 			}
    152 			else
    153 			{
    154 				return new SinglePartHttpResponse( wsdlRequest, postMethod, requestContent );
    155 			}
    156 		}
    157 		finally
    158 		{
    159 			if (postMethod != null)
    160 			{
    161 				postMethod.releaseConnection();
    162 			}
    163 			else log.error( "PostMethod is null");
    164
    165 			if( createdState )
    166 				submitContext.setProperty( SubmitContext.HTTP_STATE_PROPERTY, null );
    167 		}
    168 	}
    169
    170 	private String initRequest(WsdlRequest wsdlRequest, TimeablePostMethod postMethod, String requestContent) throws Exception
    171 	{
    172 		MimeMultipart mp = null;
    173
    174 		StringToStringMap contentIds = new StringToStringMap();
    175 		boolean isXOP = false;
    176
    177 		// preprocess only if neccessary
    178 		if( wsdlRequest.isMtomEnabled() || wsdlRequest.getAttachmentCount() > 0 )
    179 		{
    180 			try
    181 			{
    182 				mp = new MimeMultipart();
    183
    184 				MessageXmlObject requestXmlObject = new MessageXmlObject(( WsdlOperation ) wsdlRequest.getOperation(),
    185 							requestContent, true);
    186 				MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
    187 				for (MessageXmlPart requestPart : requestParts)
    188 				{
    189 					if (AttachmentUtils.prepareMessagePart(wsdlRequest, mp, requestPart, contentIds))
    190 						isXOP = true;
    191 				}
    192 				requestContent = requestXmlObject.getMessageContent();
    193 			}
    194 			catch (Exception e)
    195 			{
    196 				log.warn( "Failed to process inline/MTOM attachments; " + e );
    197 			}
    198 		}
    199
    200 		// non-multipart request?
    201 		if( !isXOP && (mp == null || mp.getCount() == 0 ) && wsdlRequest.getAttachmentCount() == 0 )
    202 		{
    203 			String encoding = StringUtils.unquote( wsdlRequest.getEncoding());
    204 			byte[] content = encoding == null ? requestContent.getBytes() : requestContent.getBytes(encoding);
    205 			postMethod.setRequestEntity(new ByteArrayRequestEntity(content));
    206 		}
    207 		else
    208 		{
    209 			// make sure..
    210 			if( mp == null )
    211 				mp = new MimeMultipart();
    212
    213 			// init root part
    214 			initRootPart(wsdlRequest, requestContent, mp, isXOP);
    215
    216 			// init mimeparts
    217 			AttachmentUtils.addMimeParts(wsdlRequest, mp, contentIds);
    218
    219 			// create request message
    220 			MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
    221 			message.setContent( mp );
    222 			message.saveChanges();
    223 			MimeMessageRequestEntity mimeMessageRequestEntity = new MimeMessageRequestEntity( message, isXOP, wsdlRequest );
    224 			postMethod.setRequestEntity( mimeMessageRequestEntity );
    225 			postMethod.setRequestHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
    226 			postMethod.setRequestHeader( "MIME-Version", "1.0" );
    227 		}
    228
    229 		return requestContent;
    230 	}
    231
    232 	/***
    233 	 * Creates root BodyPart containing message
    234 	 */
    235
    236 	private void initRootPart(WsdlRequest wsdlRequest, String requestContent, MimeMultipart mp, boolean isXOP) throws MessagingException
    237 	{
    238 		MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
    239 		rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
    240 		mp.addBodyPart( rootPart, 0 );
    241
    242 		DataHandler dataHandler = new DataHandler( new WsdlRequestDataSource( wsdlRequest, requestContent, isXOP ) );
    243 		rootPart.setDataHandler( dataHandler);
    244 	}
    245
    246
    247 }