/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.wsdl.submit.transports.http;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.rest.support.MediaTypeHandler;
import com.eviware.soapui.impl.rest.support.MediaTypeHandlerRegistry;
import com.eviware.soapui.impl.support.AbstractHttpRequestInterface;
import com.eviware.soapui.impl.support.http.HttpRequest;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.metrics.SoapUIMetrics;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.teststeps.TestRequest;
import com.eviware.soapui.model.iface.Attachment;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
import com.eviware.soapui.model.settings.Settings;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.settings.HttpSettings;
import com.eviware.soapui.settings.UISettings;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.support.types.StringToStringsMap;
import org.apache.http.Header;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.List;
public abstract class BaseHttpResponse implements HttpResponse {
private StringToStringsMap requestHeaders;
private StringToStringsMap responseHeaders;
private long timeTaken;
private long timestamp;
private String contentType;
private SSLInfo sslInfo;
private URL url;
private WeakReference<AbstractHttpRequestInterface<?>> httpRequest;
private String method;
private String version;
private StringToStringMap properties;
private byte[] rawRequestData;
private byte[] rawResponseData;
private byte[] rawResponseBody;
private int requestContentPos = -1;
private String xmlContent;
private Attachment[] attachments = new Attachment[0];
protected HTMLPageSourceDownloader downloader;
private int statusCode;
public BaseHttpResponse(ExtendedHttpMethod httpMethod, AbstractHttpRequestInterface<?> httpRequest,
PropertyExpansionContext context) {
this.httpRequest = new WeakReference<AbstractHttpRequestInterface<?>>(httpRequest);
this.timeTaken = httpMethod.getTimeTaken();
SoapUIMetrics metrics = httpMethod.getMetrics();
method = httpMethod.getMethod();
version = httpMethod.getProtocolVersion().toString();
try {
this.url = httpMethod.getURL();
} catch (Exception e1) {
SoapUI.logError(e1);
}
if (!httpMethod.isFailed()) {
Settings settings = httpRequest.getSettings();
try {
rawResponseBody = httpMethod.getResponseBody();
} catch (IOException e) {
e.printStackTrace();
}
if (settings.getBoolean(HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN)) {
timeTaken += httpMethod.getResponseReadTime();
}
// metrics.getReadTimer().add( httpMethod.getResponseReadTimeNanos() );
// metrics.getTotalTimer().add( httpMethod.getResponseReadTimeNanos() );
metrics.getReadTimer().add(httpMethod.getResponseReadTime());
metrics.getTotalTimer().add(httpMethod.getResponseReadTime());
try {
this.timestamp = System.currentTimeMillis();
this.contentType = httpMethod.getResponseContentType();
this.statusCode = extractStatusCode(httpMethod);
this.sslInfo = httpMethod.getSSLInfo();
this.url = httpMethod.getURL();
metrics.setTimestamp(getTimestamp());
metrics.setHttpStatus(getStatusCode());
} catch (Exception e) {
e.printStackTrace();
}
}
if (httpRequest instanceof TestRequest) {
TestCase tc = ((TestRequest) httpRequest).getTestStep().getTestCase();
if (tc instanceof WsdlTestCase && ((WsdlTestCase) tc).isForLoadTest()) {
initHeadersForLoadTest(httpMethod);
return;
}
}
initHeaders(httpMethod);
AbstractHttpRequestInterface<?> requestInterface = this.httpRequest.get();
if (requestInterface instanceof HttpRequest) {
boolean downloadIncludedResources = ((HttpRequest) requestInterface).getDownloadIncludedResources();
if (downloadIncludedResources) {
long beforeNanos = System.nanoTime();
addIncludedContentsAsAttachments();
long afterNanos = System.nanoTime();
timeTaken += ((afterNanos - beforeNanos) / 1000000);
metrics.getTotalTimer().add(afterNanos - beforeNanos);
context.setProperty(HTMLPageSourceDownloader.MISSING_RESOURCES_LIST, downloader.getMissingResourcesList());
}
}
}
private int extractStatusCode(ExtendedHttpMethod httpMethod) {
if (httpMethod instanceof HttpStatusHolder) {
return ((HttpStatusHolder) httpMethod).getResponseStatusCode();
} else {
return httpMethod.hasHttpResponse() ? httpMethod.getHttpResponse().getStatusLine()
.getStatusCode() : 0;
}
}
private void addIncludedContentsAsAttachments() {
downloader = new HTMLPageSourceDownloader();
try {
List<Attachment> attachmentList = downloader.downloadCssAndImages(url.toString(),
(HttpRequest) httpRequest.get());
attachments = attachmentList.toArray(new Attachment[attachmentList.size()]);
} catch (ClassCastException cce) {
attachments = new Attachment[1];
try {
attachments[0] = downloader.createAttachment(rawResponseData, url, httpRequest.get());
} catch (IOException e) {
SoapUI.log.error(e);
}
} catch (Exception e) {
SoapUI.log.error(e);
}
}
protected void initHeaders(ExtendedHttpMethod httpMethod) {
try {
ByteArrayOutputStream rawResponse = new ByteArrayOutputStream();
ByteArrayOutputStream rawRequest = new ByteArrayOutputStream();
if (!httpMethod.isFailed() && httpMethod.hasHttpResponse()) {
try {
rawResponse.write(extractStatusLine(httpMethod).getBytes());
rawResponse.write("\r\n".getBytes());
} catch (Exception ignore) {
}
}
rawRequest.write((method + " " + String.valueOf(url) + " " + version + "\r\n").getBytes());
requestHeaders = new StringToStringsMap();
Header[] headers = httpMethod.getAllHeaders();
for (Header header : headers) {
requestHeaders.put(header.getName(), header.getValue());
rawRequest.write(toExternalForm(header).getBytes());
}
responseHeaders = new StringToStringsMap();
if (!httpMethod.isFailed() && httpMethod.hasHttpResponse()) {
headers = httpMethod.getAllResponseHeaders();
for (Header header : headers) {
responseHeaders.put(header.getName(), header.getValue());
rawResponse.write(toExternalForm(header).getBytes());
}
responseHeaders.put("#status#", extractStatusLine(httpMethod));
}
if (httpMethod.getRequestEntity() != null) {
rawRequest.write("\r\n".getBytes());
if (httpMethod.getRequestEntity().isRepeatable()) {
requestContentPos = rawRequest.size();
MaxSizeByteArrayOutputStream tempOut = new MaxSizeByteArrayOutputStream(SoapUI.getSettings().getLong(
UISettings.RAW_REQUEST_MESSAGE_SIZE, 0));
httpMethod.getRequestEntity().writeTo(tempOut);
tempOut.writeTo(rawRequest);
} else {
rawRequest.write("<request data not available>".getBytes());
}
}
if (!httpMethod.isFailed() && httpMethod.hasHttpResponse() && httpMethod.getResponseBody() != null) {
rawResponse.write("\r\n".getBytes());
rawResponse.write(httpMethod.getResponseBody());
}
rawResponseData = rawResponse.toByteArray();
rawRequestData = rawRequest.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
}
private String extractStatusLine(ExtendedHttpMethod httpMethod) {
if (httpMethod instanceof HttpStatusHolder) {
return ((HttpStatusHolder) httpMethod).getResponseStatusLine();
} else {
return String.valueOf(httpMethod.getHttpResponse().getStatusLine());
}
}
public static class MaxSizeByteArrayOutputStream extends ByteArrayOutputStream {
private final long maxSize;
public MaxSizeByteArrayOutputStream(long maxSize) {
this.maxSize = maxSize;
}
@Override
public synchronized void write(int b) {
if (maxSize > 0 && size() < maxSize) {
super.write(b);
}
}
@Override
public synchronized void write(byte[] b, int off, int len) {
if (maxSize > 0 && size() < maxSize) {
if (size() + len < maxSize) {
super.write(b, off, len);
} else {
super.write(b, off, (int) (maxSize - size()));
}
}
}
@Override
public void write(byte[] b) throws IOException {
if (maxSize > 0 && size() < maxSize) {
if (size() + b.length < maxSize) {
super.write(b);
} else {
super.write(b, 0, (int) (maxSize - size()));
}
}
}
}
protected void initHeadersForLoadTest(ExtendedHttpMethod httpMethod) {
try {
requestHeaders = new StringToStringsMap();
Header[] headers = httpMethod.getAllHeaders();
for (Header header : headers) {
requestHeaders.put(header.getName(), header.getValue());
}
if (!httpMethod.isFailed() && httpMethod.hasHttpResponse()) {
responseHeaders = new StringToStringsMap();
headers = httpMethod.getHttpResponse().getAllHeaders();
for (Header header : headers) {
responseHeaders.put(header.getName(), header.getValue());
}
responseHeaders.put("#status#", extractStatusLine(httpMethod));
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public StringToStringsMap getRequestHeaders() {
return requestHeaders;
}
public StringToStringsMap getResponseHeaders() {
return responseHeaders;
}
public long getTimeTaken() {
return timeTaken;
}
public SSLInfo getSSLInfo() {
return sslInfo;
}
public long getTimestamp() {
return timestamp;
}
public String getContentType() {
return contentType;
}
public URL getURL() {
return url;
}
public AbstractHttpRequestInterface<?> getRequest() {
return httpRequest.get();
}
public int getStatusCode() {
return statusCode;
}
public Attachment[] getAttachments() {
return attachments;
}
public Attachment[] getAttachmentsForPart(String partName) {
return new Attachment[0];
}
public byte[] getRawRequestData() {
return rawRequestData;
}
public byte[] getRawResponseData() {
return rawResponseData;
}
public byte[] getRawResponseBody() {
return rawResponseBody;
}
public String getMethod() {
return method;
}
public String getHttpVersion() {
return version;
}
public void setProperty(String name, String value) {
if (properties == null) {
properties = new StringToStringMap();
}
properties.put(name, value);
}
public String getProperty(String name) {
return properties == null ? null : properties.get(name);
}
public String[] getPropertyNames() {
return properties == null ? new String[0] : properties.getKeys();
}
public String getRequestContent() {
return requestContentPos == -1 || rawRequestData == null ? null : new String(rawRequestData, requestContentPos,
rawRequestData.length - requestContentPos);
}
public String getContentAsXml() {
if (xmlContent == null) {
MediaTypeHandler typeHandler = MediaTypeHandlerRegistry.getTypeHandler(getContentType());
xmlContent = (typeHandler == null) ? "<xml/>" : typeHandler.createXmlRepresentation(this);
}
return xmlContent;
}
/**
* Returns a {@link String} representation of the header.
*
* @return stringHEAD
*/
public String toExternalForm(Header header) {
return ((null == header.getName() ? "" : header.getName()) + ": "
+ (null == header.getValue() ? "" : header.getValue()) + "\r\n");
}
}