Java tutorial
/* * soapUI, copyright (C) 2004-2012 smartbear.com * * soapUI is free software; you can redistribute it and/or modify it under the * terms of version 2.1 of the GNU Lesser General Public License as published by * the Free Software Foundation. * * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details at gnu.org. */ package com.eviware.soapui.impl.wsdl.submit.transports.http; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import org.apache.commons.httpclient.URI; import org.apache.http.Header; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.support.AbstractHttpRequestInterface; import com.eviware.soapui.impl.support.http.HttpRequestInterface; import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.impl.wsdl.submit.RequestFilter; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MimeMessageResponse; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedDeleteMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedHeadMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedOptionsMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPatchMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPutMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedTraceMethod; import com.eviware.soapui.impl.wsdl.support.PathUtils; import com.eviware.soapui.impl.wsdl.support.http.HeaderRequestInterceptor; import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport; import com.eviware.soapui.impl.wsdl.support.http.SoapUIHttpRoute; import com.eviware.soapui.impl.wsdl.support.wss.WssCrypto; import com.eviware.soapui.model.iface.Request; import com.eviware.soapui.model.iface.Response; import com.eviware.soapui.model.iface.SubmitContext; import com.eviware.soapui.model.propertyexpansion.PropertyExpander; import com.eviware.soapui.model.settings.Settings; import com.eviware.soapui.model.support.ModelSupport; import com.eviware.soapui.settings.HttpSettings; import com.eviware.soapui.support.types.StringToStringMap; import com.eviware.soapui.support.types.StringToStringsMap; import edu.umd.cs.findbugs.annotations.CheckForNull; /** * HTTP transport that uses HttpClient to send/receive SOAP messages * * @author Ole.Matzura */ public class HttpClientRequestTransport implements BaseHttpRequestTransport { private List<RequestFilter> filters = new ArrayList<RequestFilter>(); public HttpClientRequestTransport() { } public void addRequestFilter(RequestFilter filter) { filters.add(filter); } public void removeRequestFilter(RequestFilter filter) { filters.remove(filter); } public <T> void removeRequestFilter(Class<T> filterClass) { RequestFilter filter = findFilterByType(filterClass); if (filter != null) { removeRequestFilter(filter); } } public <T> void replaceRequestFilter(Class<T> filterClass, RequestFilter newFilter) { RequestFilter filter = findFilterByType(filterClass); if (filter != null) { for (int i = 0; i < filters.size(); i++) { RequestFilter oldFilter = filters.get(i); if (oldFilter == filter) { filters.remove(i); filters.add(i, newFilter); break; } } } } @CheckForNull public <T extends Object> RequestFilter findFilterByType(Class<T> filterType) { for (int i = 0; i < filters.size(); i++) { RequestFilter filter = filters.get(i); if (filter.getClass() == filterType) { return filter; } } return null; } public void abortRequest(SubmitContext submitContext) { HttpRequestBase postMethod = (HttpRequestBase) submitContext.getProperty(HTTP_METHOD); if (postMethod != null) postMethod.abort(); } public Response sendRequest(SubmitContext submitContext, Request request) throws Exception { AbstractHttpRequestInterface<?> httpRequest = (AbstractHttpRequestInterface<?>) request; HttpClientSupport.SoapUIHttpClient httpClient = HttpClientSupport.getHttpClient(); ExtendedHttpMethod httpMethod = createHttpMethod(httpRequest); boolean createdContext = false; HttpContext httpContext = (HttpContext) submitContext.getProperty(SubmitContext.HTTP_STATE_PROPERTY); if (httpContext == null) { httpContext = HttpClientSupport.createEmptyContext(); submitContext.setProperty(SubmitContext.HTTP_STATE_PROPERTY, httpContext); createdContext = true; } String localAddress = System.getProperty("soapui.bind.address", httpRequest.getBindAddress()); if (localAddress == null || localAddress.trim().length() == 0) localAddress = SoapUI.getSettings().getString(HttpSettings.BIND_ADDRESS, null); org.apache.http.HttpResponse httpResponse = null; if (localAddress != null && localAddress.trim().length() > 0) { try { httpMethod.getParams().setParameter(ConnRoutePNames.LOCAL_ADDRESS, InetAddress.getByName(localAddress)); } catch (Exception e) { SoapUI.logError(e, "Failed to set localAddress to [" + localAddress + "]"); } } submitContext.removeProperty(RESPONSE); submitContext.setProperty(HTTP_METHOD, httpMethod); submitContext.setProperty(POST_METHOD, httpMethod); submitContext.setProperty(HTTP_CLIENT, httpClient); submitContext.setProperty(REQUEST_CONTENT, httpRequest.getRequestContent()); submitContext.setProperty(WSDL_REQUEST, httpRequest); submitContext.setProperty(RESPONSE_PROPERTIES, new StringToStringMap()); for (RequestFilter filter : filters) { filter.filterRequest(submitContext, httpRequest); } try { Settings settings = httpRequest.getSettings(); // custom http headers last so they can be overridden StringToStringsMap headers = httpRequest.getRequestHeaders(); // first remove so we don't get any unwanted duplicates for (String header : headers.keySet()) { httpMethod.removeHeaders(header); } // now add for (String header : headers.keySet()) { for (String headerValue : headers.get(header)) { headerValue = PropertyExpander.expandProperties(submitContext, headerValue); httpMethod.addHeader(header, headerValue); } } // do request WsdlProject project = (WsdlProject) ModelSupport.getModelItemProject(httpRequest); WssCrypto crypto = null; if (project != null && project.getWssContainer() != null) { crypto = project.getWssContainer().getCryptoByName( PropertyExpander.expandProperties(submitContext, httpRequest.getSslKeystore())); } if (crypto != null && WssCrypto.STATUS_OK.equals(crypto.getStatus())) { httpMethod.getParams().setParameter(SoapUIHttpRoute.SOAPUI_SSL_CONFIG, crypto.getSource() + " " + crypto.getPassword()); } // dump file? httpMethod.setDumpFile(PathUtils.expandPath(httpRequest.getDumpFile(), (AbstractWsdlModelItem<?>) httpRequest, submitContext)); // include request time? if (settings.getBoolean(HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN)) httpMethod.initStartTime(); if (httpMethod.getMetrics() != null) { httpMethod.getMetrics().setHttpMethod(httpMethod.getMethod()); captureMetrics(httpMethod, httpClient); httpMethod.getMetrics().getTotalTimer().start(); } // submit! httpResponse = HttpClientSupport.execute(httpMethod, httpContext); // save request headers captured by interceptor saveRequestHeaders(httpMethod, httpContext); if (httpMethod.getMetrics() != null) { httpMethod.getMetrics().getReadTimer().stop(); httpMethod.getMetrics().getTotalTimer().stop(); } if (isRedirectResponse(httpResponse.getStatusLine().getStatusCode()) && httpRequest.isFollowRedirects()) { if (httpResponse.getEntity() != null) { EntityUtils.consume(httpResponse.getEntity()); } ExtendedGetMethod returnMethod = followRedirects(httpClient, 0, httpMethod, httpResponse, httpContext); httpMethod = returnMethod; submitContext.setProperty(HTTP_METHOD, httpMethod); } } catch (Throwable t) { httpMethod.setFailed(t); if (t instanceof Exception) throw (Exception) t; SoapUI.logError(t); throw new Exception(t); } finally { if (!httpMethod.isFailed()) { if (httpMethod.getMetrics() != null) { if (httpMethod.getMetrics().getReadTimer().getStop() == 0) { httpMethod.getMetrics().getReadTimer().stop(); } if (httpMethod.getMetrics().getTotalTimer().getStop() == 0) { httpMethod.getMetrics().getTotalTimer().stop(); } } } else { httpMethod.getMetrics().reset(); httpMethod.getMetrics().setTimestamp(System.currentTimeMillis()); captureMetrics(httpMethod, httpClient); } for (int c = filters.size() - 1; c >= 0; c--) { RequestFilter filter = filters.get(c); filter.afterRequest(submitContext, httpRequest); } if (!submitContext.hasProperty(RESPONSE)) { createDefaultResponse(submitContext, httpRequest, httpMethod); } Response response = (Response) submitContext.getProperty(BaseHttpRequestTransport.RESPONSE); StringToStringMap responseProperties = (StringToStringMap) submitContext .getProperty(BaseHttpRequestTransport.RESPONSE_PROPERTIES); for (String key : responseProperties.keySet()) { response.setProperty(key, responseProperties.get(key)); } if (createdContext) { submitContext.setProperty(SubmitContext.HTTP_STATE_PROPERTY, null); } } return (Response) submitContext.getProperty(BaseHttpRequestTransport.RESPONSE); } private boolean isRedirectResponse(int statusCode) { switch (statusCode) { case 301: case 302: case 303: case 307: return true; } return false; } private ExtendedGetMethod followRedirects(HttpClient httpClient, int redirectCount, ExtendedHttpMethod httpMethod, org.apache.http.HttpResponse httpResponse, HttpContext httpContext) throws Exception { ExtendedGetMethod getMethod = new ExtendedGetMethod(); getMethod.getMetrics().getTotalTimer().set(httpMethod.getMetrics().getTotalTimer().getStart(), httpMethod.getMetrics().getTotalTimer().getStop()); getMethod.getMetrics().setHttpMethod(httpMethod.getMethod()); captureMetrics(httpMethod, httpClient); String location = httpResponse.getFirstHeader("Location").getValue(); URI uri = new URI(new URI(httpMethod.getURI().toString(), true), location, true); java.net.URI newUri = new java.net.URI(uri.getScheme(), uri.getUserinfo(), uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); getMethod.setURI(newUri); org.apache.http.HttpResponse response = HttpClientSupport.execute(getMethod, httpContext); if (isRedirectResponse(response.getStatusLine().getStatusCode())) { if (redirectCount == 10) throw new Exception("Maximum number of Redirects reached [10]"); try { getMethod = followRedirects(httpClient, redirectCount + 1, getMethod, response, httpContext); } finally { //getMethod.releaseConnection(); } } for (Header header : httpMethod.getAllHeaders()) getMethod.addHeader(header); return getMethod; } private void createDefaultResponse(SubmitContext submitContext, AbstractHttpRequestInterface<?> httpRequest, ExtendedHttpMethod httpMethod) { String requestContent = (String) submitContext.getProperty(BaseHttpRequestTransport.REQUEST_CONTENT); // check content-type for multiplart String responseContentTypeHeader = null; if (httpMethod.hasHttpResponse() && httpMethod.getHttpResponse().getEntity() != null) { Header h = httpMethod.getHttpResponse().getEntity().getContentType(); responseContentTypeHeader = h.toString(); } Response response = null; if (responseContentTypeHeader != null && responseContentTypeHeader.toUpperCase().startsWith("MULTIPART")) { response = new MimeMessageResponse(httpRequest, httpMethod, requestContent, submitContext); } else { response = new SinglePartHttpResponse(httpRequest, httpMethod, requestContent, submitContext); } submitContext.setProperty(BaseHttpRequestTransport.RESPONSE, response); } private ExtendedHttpMethod createHttpMethod(AbstractHttpRequestInterface<?> httpRequest) { if (httpRequest instanceof HttpRequestInterface<?>) { HttpRequestInterface<?> restRequest = (HttpRequestInterface<?>) httpRequest; switch (restRequest.getMethod()) { case GET: return new ExtendedGetMethod(); case HEAD: return new ExtendedHeadMethod(); case DELETE: return new ExtendedDeleteMethod(); case PUT: return new ExtendedPutMethod(); case OPTIONS: return new ExtendedOptionsMethod(); case TRACE: return new ExtendedTraceMethod(); case PATCH: return new ExtendedPatchMethod(); } } ExtendedPostMethod extendedPostMethod = new ExtendedPostMethod(); extendedPostMethod.setAfterRequestInjection(httpRequest.getAfterRequestInjection()); return extendedPostMethod; } private void captureMetrics(ExtendedHttpMethod httpMethod, HttpClient httpClient) { try { httpMethod.getMetrics() .setIpAddress(InetAddress.getByName(httpMethod.getURI().getHost()).getHostAddress()); httpMethod.getMetrics().setPort(httpMethod.getURI().getPort(), httpClient.getConnectionManager() .getSchemeRegistry().getScheme(httpMethod.getURI().getScheme()).getDefaultPort()); } catch (UnknownHostException uhe) { /* ignore */ } catch (IllegalStateException ise) { /* ignore */ } } private void saveRequestHeaders(ExtendedHttpMethod httpMethod, HttpContext httpContext) { List<Header> requestHeaders = (List<Header>) httpContext .getAttribute(HeaderRequestInterceptor.SOAPUI_REQUEST_HEADERS); if (requestHeaders != null) { for (Header header : requestHeaders) { Header[] existingHeaders = httpMethod.getHeaders(header.getName()); int c = 0; for (; c < existingHeaders.length; c++) if (existingHeaders[c].getValue().equals(header.getValue())) break; if (c == existingHeaders.length) httpMethod.addHeader(header); } } } }