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  		if( postMethod != null )
    73  			postMethod.abort();
    74  	}
    75
    76  	public Response sendRequest( SubmitContext submitContext, WsdlRequest wsdlRequest ) throws Exception
    77  	{
    78  		HttpClient httpClient = HttpClientSupport.getHttpClient();
    79  		TimeablePostMethod postMethod = new TimeablePostMethod();
    80  		boolean createdState = false;
    81
    82  		HttpState httpState = (HttpState) submitContext.getProperty(SubmitContext.HTTP_STATE_PROPERTY);
    83  		if( httpState == null )
    84  		{
    85  		   httpState = new HttpState();
    86  		   submitContext.setProperty( SubmitContext.HTTP_STATE_PROPERTY, httpState );
    87  		   createdState = true;
    88  		}
    89
    90  		HostConfiguration hostConfiguration = new HostConfiguration();
    91
    92  		String localAddress = System.getProperty( "soapui.bind.address", wsdlRequest.getBindAddress() );
    93  		if( localAddress == null || localAddress.trim().length() == 0 )
    94  			localAddress = SoapUI.getSettings().getString( HttpSettings.BIND_ADDRESS, null );
    95
    96  		if( localAddress != null && localAddress.trim().length() > 0 )
    97  		{
    98  			try
    99  			{
    100 				hostConfiguration.setLocalAddress( InetAddress.getByName( localAddress ));
    101 			}
    102 			catch( Exception e )
    103 			{
    104 				SoapUI.logError( e );
    105 			}
    106 		}
    107
    108 		submitContext.setProperty( POST_METHOD, postMethod );
    109 		submitContext.setProperty( HTTP_CLIENT, httpClient );
    110 		submitContext.setProperty( REQUEST_CONTENT, wsdlRequest.getRequestContent() );
    111 		submitContext.setProperty( HOST_CONFIGURATION, hostConfiguration );
    112 		submitContext.setProperty( WSDL_REQUEST, wsdlRequest );
    113
    114 		for( RequestFilter filter : filters )
    115 		{
    116 			filter.filterRequest( submitContext, wsdlRequest );
    117 		}
    118
    119 		try
    120 		{
    121 			Settings settings = wsdlRequest.getSettings();
    122
    123 			// get request content
    124 			String requestContent = (String) submitContext.getProperty(REQUEST_CONTENT);
    125
    126 			// init
    127 			requestContent = initRequest(wsdlRequest, postMethod, requestContent);
    128
    129 			// include request time?
    130 			if (settings.getBoolean(HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN))
    131 				postMethod.initStartTime();
    132
    133 			//	custom http headers last so they can be overridden
    134 			StringToStringMap headers = wsdlRequest.getRequestHeaders();
    135 			for( String header : headers.keySet() )
    136 			{
    137 				String headerValue = headers.get( header );
    138 				headerValue = PropertyExpansionRequestFilter.expandProperties( submitContext, headerValue );
    139 				postMethod.setRequestHeader( header, headerValue );
    140 			}
    141
    142 			//	do request
    143 			httpClient.executeMethod(hostConfiguration, postMethod, httpState);
    144
    145 			Header responseContentTypeHeader = postMethod.getResponseHeader( "Content-Type" );
    146
    147 			if( !settings.getBoolean( WsdlRequest.INLINE_RESPONSE_ATTACHMENTS ) &&
    148 				 responseContentTypeHeader != null &&
    149 				 responseContentTypeHeader.getValue().toUpperCase().startsWith( "MULTIPART" ))
    150 			{
    151 				return new MimeMessageResponse( wsdlRequest, postMethod, requestContent );
    152 			}
    153 			else
    154 			{
    155 				return new SinglePartHttpResponse( wsdlRequest, postMethod, requestContent );
    156 			}
    157 		}
    158 		finally
    159 		{
    160 			if (postMethod != null)
    161 			{
    162 				postMethod.releaseConnection();
    163 			}
    164 			else log.error( "PostMethod is null");
    165
    166 			if( createdState )
    167 				submitContext.setProperty( SubmitContext.HTTP_STATE_PROPERTY, null );
    168 		}
    169 	}
    170
    171 	private String initRequest(WsdlRequest wsdlRequest, TimeablePostMethod postMethod, String requestContent) throws Exception
    172 	{
    173 		MimeMultipart mp = null;
    174
    175 		StringToStringMap contentIds = new StringToStringMap();
    176 		boolean isXOP = wsdlRequest.isMtomEnabled() && wsdlRequest.isForceMtom();
    177
    178 		// preprocess only if neccessary
    179 		if( wsdlRequest.isMtomEnabled() || wsdlRequest.getAttachmentCount() > 0 )
    180 		{
    181 			try
    182 			{
    183 				mp = new MimeMultipart();
    184
    185 				MessageXmlObject requestXmlObject = new MessageXmlObject(( WsdlOperation ) wsdlRequest.getOperation(),
    186 							requestContent, true);
    187 				MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
    188 				for (MessageXmlPart requestPart : requestParts)
    189 				{
    190 					if (AttachmentUtils.prepareMessagePart(wsdlRequest, mp, requestPart, contentIds))
    191 						isXOP = true;
    192 				}
    193 				requestContent = requestXmlObject.getMessageContent();
    194 			}
    195 			catch (Exception e)
    196 			{
    197 				log.warn( "Failed to process inline/MTOM attachments; " + e );
    198 			}
    199 		}
    200
    201 		// non-multipart request?
    202 		if( !isXOP && (mp == null || mp.getCount() == 0 ) && wsdlRequest.getAttachmentCount() == 0 )
    203 		{
    204 			String encoding = StringUtils.unquote( wsdlRequest.getEncoding());
    205 			byte[] content = encoding == null ? requestContent.getBytes() : requestContent.getBytes(encoding);
    206 			postMethod.setRequestEntity(new ByteArrayRequestEntity(content));
    207 		}
    208 		else
    209 		{
    210 			// make sure..
    211 			if( mp == null )
    212 				mp = new MimeMultipart();
    213
    214 			// init root part
    215 			initRootPart(wsdlRequest, requestContent, mp, isXOP);
    216
    217 			// init mimeparts
    218 			AttachmentUtils.addMimeParts(wsdlRequest, mp, contentIds);
    219
    220 			// create request message
    221 			MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
    222 			message.setContent( mp );
    223 			message.saveChanges();
    224 			MimeMessageRequestEntity mimeMessageRequestEntity = new MimeMessageRequestEntity( message, isXOP, wsdlRequest );
    225 			postMethod.setRequestEntity( mimeMessageRequestEntity );
    226 			postMethod.setRequestHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
    227 			postMethod.setRequestHeader( "MIME-Version", "1.0" );
    228 		}
    229
    230 		return requestContent;
    231 	}
    232
    233 	/***
    234 	 * Creates root BodyPart containing message
    235 	 */
    236
    237 	private void initRootPart(WsdlRequest wsdlRequest, String requestContent, MimeMultipart mp, boolean isXOP) throws MessagingException
    238 	{
    239 		MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
    240 		rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
    241 		mp.addBodyPart( rootPart, 0 );
    242
    243 		DataHandler dataHandler = new DataHandler( new WsdlRequestDataSource( wsdlRequest, requestContent, isXOP ) );
    244 		rootPart.setDataHandler( dataHandler);
    245 	}
    246
    247
    248 }