001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.submit.transports.http;
014:
015: import java.net.InetAddress;
016: import java.util.ArrayList;
017: import java.util.List;
018:
019: import javax.activation.DataHandler;
020: import javax.mail.MessagingException;
021: import javax.mail.internet.MimeBodyPart;
022: import javax.mail.internet.MimeMessage;
023: import javax.mail.internet.MimeMultipart;
024: import javax.mail.internet.PreencodedMimeBodyPart;
025:
026: import org.apache.commons.httpclient.Header;
027: import org.apache.commons.httpclient.HostConfiguration;
028: import org.apache.commons.httpclient.HttpClient;
029: import org.apache.commons.httpclient.HttpState;
030: import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
031: import org.apache.log4j.Logger;
032:
033: import com.eviware.soapui.SoapUI;
034: import com.eviware.soapui.impl.wsdl.WsdlOperation;
035: import com.eviware.soapui.impl.wsdl.WsdlRequest;
036: import com.eviware.soapui.impl.wsdl.submit.RequestFilter;
037: import com.eviware.soapui.impl.wsdl.submit.filters.PropertyExpansionRequestFilter;
038: import com.eviware.soapui.impl.wsdl.support.MessageXmlObject;
039: import com.eviware.soapui.impl.wsdl.support.MessageXmlPart;
040: import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
041: import com.eviware.soapui.model.iface.Response;
042: import com.eviware.soapui.model.iface.SubmitContext;
043: import com.eviware.soapui.model.settings.Settings;
044: import com.eviware.soapui.settings.HttpSettings;
045: import com.eviware.soapui.support.StringUtils;
046: import com.eviware.soapui.support.types.StringToStringMap;
047:
048: /**
049: * HTTP transport that uses HttpClient to send/receive SOAP messages
050: *
051: * @author Ole.Matzura
052: */
053:
054: public class HttpClientRequestTransport implements
055: BaseHttpRequestTransport {
056: private List<RequestFilter> filters = new ArrayList<RequestFilter>();
057: private final static Logger log = Logger
058: .getLogger(HttpClientRequestTransport.class);
059:
060: public void addRequestFilter(RequestFilter filter) {
061: filters.add(filter);
062: }
063:
064: public void removeRequestFilter(RequestFilter filter) {
065: filters.remove(filter);
066: }
067:
068: public void abortRequest(SubmitContext submitContext) {
069: TimeablePostMethod postMethod = (TimeablePostMethod) submitContext
070: .getProperty(POST_METHOD);
071: postMethod.abort();
072: }
073:
074: public Response sendRequest(SubmitContext submitContext,
075: WsdlRequest wsdlRequest) throws Exception {
076: HttpClient httpClient = HttpClientSupport.getHttpClient();
077: TimeablePostMethod postMethod = new TimeablePostMethod();
078: boolean createdState = false;
079:
080: HttpState httpState = (HttpState) submitContext
081: .getProperty(SubmitContext.HTTP_STATE_PROPERTY);
082: if (httpState == null) {
083: httpState = new HttpState();
084: submitContext.setProperty(
085: SubmitContext.HTTP_STATE_PROPERTY, httpState);
086: createdState = true;
087: }
088:
089: HostConfiguration hostConfiguration = new HostConfiguration();
090:
091: String localAddress = System.getProperty("soapui.bind.address",
092: wsdlRequest.getBindAddress());
093: if (localAddress == null || localAddress.trim().length() == 0)
094: localAddress = SoapUI.getSettings().getString(
095: HttpSettings.BIND_ADDRESS, null);
096:
097: if (localAddress != null && localAddress.trim().length() > 0) {
098: try {
099: hostConfiguration.setLocalAddress(InetAddress
100: .getByName(localAddress));
101: } catch (Exception e) {
102: SoapUI.logError(e);
103: }
104: }
105:
106: submitContext.setProperty(POST_METHOD, postMethod);
107: submitContext.setProperty(HTTP_CLIENT, httpClient);
108: submitContext.setProperty(REQUEST_CONTENT, wsdlRequest
109: .getRequestContent());
110: submitContext
111: .setProperty(HOST_CONFIGURATION, hostConfiguration);
112: submitContext.setProperty(WSDL_REQUEST, wsdlRequest);
113:
114: for (RequestFilter filter : filters) {
115: filter.filterRequest(submitContext, wsdlRequest);
116: }
117:
118: try {
119: Settings settings = wsdlRequest.getSettings();
120:
121: // get request content
122: String requestContent = (String) submitContext
123: .getProperty(REQUEST_CONTENT);
124:
125: // init
126: requestContent = initRequest(wsdlRequest, postMethod,
127: requestContent);
128:
129: // include request time?
130: if (settings
131: .getBoolean(HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN))
132: postMethod.initStartTime();
133:
134: // custom http headers last so they can be overridden
135: StringToStringMap headers = wsdlRequest.getRequestHeaders();
136: for (String header : headers.keySet()) {
137: String headerValue = headers.get(header);
138: headerValue = PropertyExpansionRequestFilter
139: .expandProperties(submitContext, headerValue);
140: postMethod.setRequestHeader(header, headerValue);
141: }
142:
143: // do request
144: httpClient.executeMethod(hostConfiguration, postMethod,
145: httpState);
146:
147: Header responseContentTypeHeader = postMethod
148: .getResponseHeader("Content-Type");
149:
150: if (!settings
151: .getBoolean(WsdlRequest.INLINE_RESPONSE_ATTACHMENTS)
152: && responseContentTypeHeader != null
153: && responseContentTypeHeader.getValue()
154: .toUpperCase().startsWith("MULTIPART")) {
155: return new MimeMessageResponse(wsdlRequest, postMethod,
156: requestContent);
157: } else {
158: return new SinglePartHttpResponse(wsdlRequest,
159: postMethod, requestContent);
160: }
161: } finally {
162: if (postMethod != null) {
163: postMethod.releaseConnection();
164: } else
165: log.error("PostMethod is null");
166:
167: if (createdState)
168: submitContext.setProperty(
169: SubmitContext.HTTP_STATE_PROPERTY, null);
170: }
171: }
172:
173: private String initRequest(WsdlRequest wsdlRequest,
174: TimeablePostMethod postMethod, String requestContent)
175: throws Exception {
176: MimeMultipart mp = null;
177:
178: StringToStringMap contentIds = new StringToStringMap();
179: boolean isXOP = false;
180:
181: // preprocess only if neccessary
182: if (wsdlRequest.isMtomEnabled()
183: || wsdlRequest.getAttachmentCount() > 0) {
184: try {
185: mp = new MimeMultipart();
186:
187: MessageXmlObject requestXmlObject = new MessageXmlObject(
188: (WsdlOperation) wsdlRequest.getOperation(),
189: requestContent, true);
190: MessageXmlPart[] requestParts = requestXmlObject
191: .getMessageParts();
192: for (MessageXmlPart requestPart : requestParts) {
193: if (AttachmentUtils.prepareMessagePart(wsdlRequest,
194: mp, requestPart, contentIds))
195: isXOP = true;
196: }
197: requestContent = requestXmlObject.getMessageContent();
198: } catch (Exception e) {
199: log.warn("Failed to process inline/MTOM attachments; "
200: + e);
201: }
202: }
203:
204: // non-multipart request?
205: if (!isXOP && (mp == null || mp.getCount() == 0)
206: && wsdlRequest.getAttachmentCount() == 0) {
207: String encoding = StringUtils.unquote(wsdlRequest
208: .getEncoding());
209: byte[] content = encoding == null ? requestContent
210: .getBytes() : requestContent.getBytes(encoding);
211: postMethod.setRequestEntity(new ByteArrayRequestEntity(
212: content));
213: } else {
214: // make sure..
215: if (mp == null)
216: mp = new MimeMultipart();
217:
218: // init root part
219: initRootPart(wsdlRequest, requestContent, mp, isXOP);
220:
221: // init mimeparts
222: AttachmentUtils.addMimeParts(wsdlRequest, mp, contentIds);
223:
224: // create request message
225: MimeMessage message = new MimeMessage(
226: AttachmentUtils.JAVAMAIL_SESSION);
227: message.setContent(mp);
228: message.saveChanges();
229: MimeMessageRequestEntity mimeMessageRequestEntity = new MimeMessageRequestEntity(
230: message, isXOP, wsdlRequest);
231: postMethod.setRequestEntity(mimeMessageRequestEntity);
232: postMethod.setRequestHeader("Content-Type",
233: mimeMessageRequestEntity.getContentType());
234: postMethod.setRequestHeader("MIME-Version", "1.0");
235: }
236:
237: return requestContent;
238: }
239:
240: /**
241: * Creates root BodyPart containing message
242: */
243:
244: private void initRootPart(WsdlRequest wsdlRequest,
245: String requestContent, MimeMultipart mp, boolean isXOP)
246: throws MessagingException {
247: MimeBodyPart rootPart = new PreencodedMimeBodyPart("8bit");
248: rootPart.setContentID(AttachmentUtils.ROOTPART_SOAPUI_ORG);
249: mp.addBodyPart(rootPart, 0);
250:
251: DataHandler dataHandler = new DataHandler(
252: new WsdlRequestDataSource(wsdlRequest, requestContent,
253: isXOP));
254: rootPart.setDataHandler(dataHandler);
255: }
256:
257: }
|