com.eviware.soapui.impl.support.AbstractMockResponse.java Source code

Java tutorial

Introduction

Here is the source code for com.eviware.soapui.impl.support.AbstractMockResponse.java

Source

/*
 * SoapUI, Copyright (C) 2004-2017 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.support;

import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.BaseMockResponseConfig;
import com.eviware.soapui.config.CompressedStringConfig;
import com.eviware.soapui.config.HeaderConfig;
import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
import com.eviware.soapui.impl.wsdl.MutableWsdlAttachmentContainer;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.mock.DispatchException;
import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunContext;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.AttachmentUtils;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MimeMessageMockResponseEntity;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MockResponseDataSource;
import com.eviware.soapui.impl.wsdl.support.CompressedStringSupport;
import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
import com.eviware.soapui.impl.wsdl.support.MapTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.support.MessageXmlObject;
import com.eviware.soapui.impl.wsdl.support.MessageXmlPart;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.TestPropertyHolder;
import com.eviware.soapui.model.iface.Operation;
import com.eviware.soapui.model.mock.MockOperation;
import com.eviware.soapui.model.mock.MockRequest;
import com.eviware.soapui.model.mock.MockResponse;
import com.eviware.soapui.model.mock.MockResult;
import com.eviware.soapui.model.mock.MockRunContext;
import com.eviware.soapui.model.mock.MockRunner;
import com.eviware.soapui.model.mock.MockService;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.settings.CommonSettings;
import com.eviware.soapui.support.scripting.ScriptEnginePool;
import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.support.types.StringToStringsMap;
import com.eviware.soapui.support.xml.XmlUtils;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.ws.security.WSSecurityException;

import javax.activation.DataHandler;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.PreencodedMimeBodyPart;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public abstract class AbstractMockResponse<MockResponseConfigType extends BaseMockResponseConfig>
        extends AbstractWsdlModelItem<MockResponseConfigType>
        implements MockResponse, MutableWsdlAttachmentContainer, PropertyExpansionContainer, TestPropertyHolder {
    public static final String AUTO_RESPONSE_COMPRESSION = "<auto>";
    public static final String NO_RESPONSE_COMPRESSION = "<none>";
    private MapTestPropertyHolder propertyHolder;

    private String responseContent;
    private MockResult mockResult;
    private ScriptEnginePool scriptEnginePool;

    public AbstractMockResponse(MockResponseConfigType config, MockOperation operation, String icon) {
        super(config, operation, icon);
        scriptEnginePool = new ScriptEnginePool(this);
        scriptEnginePool.setScript(getScript());
        propertyHolder = new MapTestPropertyHolder(this);
        propertyHolder.addProperty("Request");

        if (!config.isSetHttpResponseStatus()) {
            config.setHttpResponseStatus("" + HttpStatus.SC_OK);
        }

    }

    @Override
    public void setConfig(MockResponseConfigType config) {
        super.setConfig(config);

        if (scriptEnginePool != null) {
            scriptEnginePool.setScript(getScript());
        }
    }

    public String getResponseContent() {
        if (getConfig().getResponseContent() == null) {
            getConfig().addNewResponseContent();
        }

        if (responseContent == null) {
            responseContent = CompressedStringSupport.getString(getConfig().getResponseContent());
        }

        return responseContent;
    }

    public void setResponseContent(String responseContent) {
        String oldContent = getResponseContent();
        if (responseContent != null && responseContent.equals(oldContent)) {
            return;
        }

        this.responseContent = responseContent;

        setConfigResponseContent(responseContent);

        notifyPropertyChanged(RESPONSE_CONTENT_PROPERTY, oldContent, responseContent);
    }

    private void setConfigResponseContent(String responseContent) {
        CompressedStringConfig compressedResponseContent = CompressedStringConfig.Factory.newInstance();
        compressedResponseContent.setStringValue(responseContent);
        getConfig().setResponseContent(compressedResponseContent);
    }

    public StringToStringsMap getResponseHeaders() {
        StringToStringsMap result = new StringToStringsMap();
        List<HeaderConfig> headerList = getConfig().getHeaderList();
        for (HeaderConfig header : headerList) {
            result.add(header.getName(), header.getValue());
        }

        return result;
    }

    public void setResponseHttpStatus(int httpStatus) {
        getConfig().setHttpResponseStatus("" + httpStatus);
    }

    public int getResponseHttpStatus() {

        if (getConfig().getHttpResponseStatus() != null) {
            return Integer.valueOf(getConfig().getHttpResponseStatus());

        } else {
            return HttpStatus.SC_OK;
        }
    }

    public String getResponseCompression() {
        if (getConfig().isSetCompression()) {
            return getConfig().getCompression();
        } else {
            return AUTO_RESPONSE_COMPRESSION;
        }
    }

    public void setMockResult(MockResult mockResult) {
        MockResult oldResult = this.mockResult;
        this.mockResult = mockResult;
        notifyPropertyChanged(mockresultProperty(), oldResult, mockResult);
    }

    public MockResult getMockResult() {
        return mockResult;
    }

    protected abstract String mockresultProperty();

    public String getScript() {
        return getConfig().isSetScript() ? getConfig().getScript().getStringValue() : null;
    }

    public void evaluateScript(MockRequest request) throws Exception {
        String script = getScript();
        if (script == null || script.trim().length() == 0) {
            return;
        }

        MockService mockService = getMockOperation().getMockService();
        MockRunner mockRunner = mockService.getMockRunner();
        MockRunContext context = mockRunner == null ? new WsdlMockRunContext(mockService, null)
                : mockRunner.getMockContext();

        context.setMockResponse(this);

        SoapUIScriptEngine scriptEngine = scriptEnginePool.getScriptEngine();

        try {
            scriptEngine.setVariable("context", context);
            scriptEngine.setVariable("requestContext", request == null ? null : request.getRequestContext());
            scriptEngine.setVariable("mockContext", context);
            scriptEngine.setVariable("mockRequest", request);
            scriptEngine.setVariable("mockResponse", this);
            scriptEngine.setVariable("log", SoapUI.ensureGroovyLog());

            scriptEngine.run();
        } catch (RuntimeException e) {
            throw new Exception(e.getMessage(), e);
        } finally {
            scriptEnginePool.returnScriptEngine(scriptEngine);
        }
    }

    public void setScript(String script) {
        String oldScript = getScript();
        if (!script.equals(oldScript)) {
            if (!getConfig().isSetScript()) {
                getConfig().addNewScript();
            }
            getConfig().getScript().setStringValue(script);

            scriptEnginePool.setScript(script);
        }
    }

    @Override
    public void release() {
        super.release();
        scriptEnginePool.release();
    }

    public MockResult execute(MockRequest request, MockResult result) throws DispatchException {
        try {
            getProperty("Request").setValue(request.getRequestContent());

            long delay = getResponseDelay();
            if (delay > 0) {
                Thread.sleep(delay);
            }

            String script = getScript();
            if (script != null && script.trim().length() > 0) {
                evaluateScript(request);
            }

            String responseContent = getResponseContent();

            // create merged context
            WsdlMockRunContext context = new WsdlMockRunContext(request.getContext().getMockService(), null);
            context.setMockResponse(this);

            // casting below cause WsdlMockRunContext is both a MockRunContext AND a Map<String,Object>
            context.putAll((WsdlMockRunContext) request.getContext());
            context.putAll((WsdlMockRunContext) request.getRequestContext());

            StringToStringsMap responseHeaders = getResponseHeaders();
            for (Map.Entry<String, List<String>> headerEntry : responseHeaders.entrySet()) {
                for (String value : headerEntry.getValue()) {
                    result.addHeader(headerEntry.getKey(), PropertyExpander.expandProperties(context, value));
                }
            }

            responseContent = PropertyExpander.expandProperties(context, responseContent, isEntitizeProperties());

            responseContent = executeSpecifics(request, responseContent, context);

            if (!result.isCommitted()) {
                responseContent = writeResponse(result, responseContent);
            }

            result.setResponseContent(responseContent);

            setMockResult(result);

            return result;
        } catch (Throwable e) {
            SoapUI.logError(e);
            throw new DispatchException(e);
        }
    }

    public String writeResponse(MockResult result, String responseContent) throws Exception {
        MimeMultipart mp = null;

        Operation operation = getMockOperation().getOperation();

        // variables needed for both multipart sections....
        boolean isXOP = isMtomEnabled() && isForceMtom();
        StringToStringMap contentIds = new StringToStringMap();

        // only support multipart for wsdl currently.....
        if (operation instanceof WsdlOperation) {
            if (operation == null) {
                throw new IllegalStateException("Missing WsdlOperation for mock response");
            }

            // preprocess only if neccessary
            if (isMtomEnabled() || isInlineFilesEnabled() || getAttachmentCount() > 0) {
                try {
                    mp = new MimeMultipart();

                    WsdlOperation wsdlOperation = ((WsdlOperation) operation);
                    MessageXmlObject requestXmlObject = createMessageXmlObject(responseContent, wsdlOperation);
                    MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
                    for (MessageXmlPart requestPart : requestParts) {
                        if (prepareMessagePart(mp, contentIds, requestPart)) {
                            isXOP = true;
                        }
                    }
                    responseContent = requestXmlObject.getMessageContent();
                } catch (Exception e) {
                    SoapUI.logError(e);
                }
            }

            responseContent = removeEmptyContent(responseContent);
        }

        if (isStripWhitespaces()) {
            responseContent = XmlUtils.stripWhitespaces(responseContent);
        }

        MockRequest request = result.getMockRequest();
        request.getHttpResponse().setStatus(this.getResponseHttpStatus());

        ByteArrayOutputStream outData = new ByteArrayOutputStream();

        // non-multipart request?
        String responseCompression = getResponseCompression();
        if (!isXOP && (mp == null || mp.getCount() == 0) && getAttachmentCount() == 0) {
            String encoding = getEncoding();
            if (responseContent == null) {
                responseContent = "";
            }

            byte[] content = encoding == null ? responseContent.getBytes() : responseContent.getBytes(encoding);

            if (!result.getResponseHeaders().containsKeyIgnoreCase("Content-Type")) {
                result.setContentType(getContentType());
            }

            String acceptEncoding = result.getMockRequest().getRequestHeaders().get("Accept-Encoding", "");
            if (AUTO_RESPONSE_COMPRESSION.equals(responseCompression) && acceptEncoding != null
                    && acceptEncoding.toUpperCase().contains("GZIP")) {
                if (!headerExists("Content-Encoding", "gzip", result)) {
                    result.addHeader("Content-Encoding", "gzip");
                }
                outData.write(CompressionSupport.compress(CompressionSupport.ALG_GZIP, content));
            } else if (AUTO_RESPONSE_COMPRESSION.equals(responseCompression) && acceptEncoding != null
                    && acceptEncoding.toUpperCase().contains("DEFLATE")) {
                result.addHeader("Content-Encoding", "deflate");
                outData.write(CompressionSupport.compress(CompressionSupport.ALG_DEFLATE, content));
            } else {
                outData.write(content);
            }
        } else // won't get here if rest at the moment...
        {
            // make sure..
            if (mp == null) {
                mp = new MimeMultipart();
            }

            // init root part
            initRootPart(responseContent, mp, isXOP);

            // init mimeparts
            AttachmentUtils.addMimeParts(this, Arrays.asList(getAttachments()), mp, contentIds);

            // create request message
            MimeMessage message = new MimeMessage(AttachmentUtils.JAVAMAIL_SESSION);
            message.setContent(mp);
            message.saveChanges();
            MimeMessageMockResponseEntity mimeMessageRequestEntity = new MimeMessageMockResponseEntity(message,
                    isXOP, this);

            result.addHeader("Content-Type", mimeMessageRequestEntity.getContentType().getValue());
            result.addHeader("MIME-Version", "1.0");
            mimeMessageRequestEntity.writeTo(outData);
        }

        if (outData.size() > 0) {
            byte[] data = outData.toByteArray();

            if (responseCompression.equals(CompressionSupport.ALG_DEFLATE)
                    || responseCompression.equals(CompressionSupport.ALG_GZIP)) {
                result.addHeader("Content-Encoding", responseCompression);
                data = CompressionSupport.compress(responseCompression, data);
            }
            if (result.getResponseHeaders().get("Transfer-Encoding") == null) {
                result.addHeader("Content-Length", "" + data.length);
            }
            result.writeRawResponseData(data);
        }

        return responseContent;
    }

    private boolean headerExists(String headerName, String headerValue, MockResult result) {
        StringToStringsMap resultResponseHeaders = result.getResponseHeaders();

        if (resultResponseHeaders.containsKeyIgnoreCase(headerName)) {
            if (resultResponseHeaders.get(headerName).contains(headerValue)) {
                return true;
            }
        }

        return false;
    }

    public boolean prepareMessagePart(MimeMultipart mp, StringToStringMap contentIds, MessageXmlPart requestPart)
            throws Exception {
        return AttachmentUtils.prepareMessagePart(this, mp, requestPart, contentIds);
    }

    public MessageXmlObject createMessageXmlObject(String responseContent, WsdlOperation wsdlOperation) {
        return new MessageXmlObject(wsdlOperation, responseContent, false);
    }

    private void initRootPart(String requestContent, MimeMultipart mp, boolean isXOP) throws MessagingException {
        MimeBodyPart rootPart = new PreencodedMimeBodyPart("8bit");
        rootPart.setContentID(AttachmentUtils.ROOTPART_SOAPUI_ORG);
        mp.addBodyPart(rootPart, 0);

        DataHandler dataHandler = new DataHandler(new MockResponseDataSource(this, requestContent, isXOP));
        rootPart.setDataHandler(dataHandler);
    }

    protected abstract String removeEmptyContent(String responseContent);

    public void setResponseHeaders(StringToStringsMap headers) {
        StringToStringsMap oldHeaders = getResponseHeaders();

        getConfig().setHeaderArray(new HeaderConfig[0]);

        for (Map.Entry<String, List<String>> header : headers.entrySet()) {
            for (String value : header.getValue()) {
                HeaderConfig headerConfig = getConfig().addNewHeader();
                headerConfig.setName(header.getKey());
                headerConfig.setValue(value);
            }
        }

        notifyPropertyChanged(WsdlMockResponse.HEADERS_PROPERTY, oldHeaders, headers);
    }

    protected abstract String executeSpecifics(MockRequest request, String responseContent,
            WsdlMockRunContext context) throws IOException, WSSecurityException;

    public boolean isEntitizeProperties() {
        return getSettings().getBoolean(CommonSettings.ENTITIZE_PROPERTIES);
    }

    public abstract long getResponseDelay();

    public abstract boolean isForceMtom();

    public abstract boolean isStripWhitespaces();

    public void addTestPropertyListener(TestPropertyListener listener) {
        propertyHolder.addTestPropertyListener(listener);
    }

    public ModelItem getModelItem() {
        return propertyHolder.getModelItem();
    }

    public Map<String, TestProperty> getProperties() {
        return propertyHolder.getProperties();
    }

    public TestProperty getProperty(String name) {
        return propertyHolder.getProperty(name);
    }

    public String[] getPropertyNames() {
        return propertyHolder.getPropertyNames();
    }

    public String getPropertyValue(String name) {
        return propertyHolder.getPropertyValue(name);
    }

    public boolean hasProperty(String name) {
        return propertyHolder.hasProperty(name);
    }

    public void removeTestPropertyListener(TestPropertyListener listener) {
        propertyHolder.removeTestPropertyListener(listener);
    }

    public void setPropertyValue(String name, String value) {
        propertyHolder.setPropertyValue(name, value);
    }

    public TestProperty getPropertyAt(int index) {
        return propertyHolder.getPropertyAt(index);
    }

    public int getPropertyCount() {
        return propertyHolder.getPropertyCount();
    }

    public List<TestProperty> getPropertyList() {
        return propertyHolder.getPropertyList();
    }

    public String getEncoding() {
        return getConfig().getEncoding();
    }

    public void setEncoding(String encoding) {
        getConfig().setEncoding(encoding);
    }
}