/*
* 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.mock;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.AttachmentConfig;
import com.eviware.soapui.config.MockResponseConfig;
import com.eviware.soapui.impl.support.AbstractMockResponse;
import com.eviware.soapui.impl.wsdl.HttpAttachmentPart;
import com.eviware.soapui.impl.wsdl.WsdlContentPart;
import com.eviware.soapui.impl.wsdl.WsdlHeaderPart;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.submit.filters.RemoveEmptyContentRequestFilter;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.AttachmentUtils;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.BodyPartAttachment;
import com.eviware.soapui.impl.wsdl.support.CompressedStringSupport;
import com.eviware.soapui.impl.wsdl.support.FileAttachment;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.support.IconAnimator;
import com.eviware.soapui.impl.wsdl.support.MockFileAttachment;
import com.eviware.soapui.impl.wsdl.support.WsdlAttachment;
import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
import com.eviware.soapui.impl.wsdl.support.wsa.WsaConfig;
import com.eviware.soapui.impl.wsdl.support.wsa.WsaContainer;
import com.eviware.soapui.impl.wsdl.support.wsa.WsaUtils;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils.SoapHeader;
import com.eviware.soapui.impl.wsdl.support.wss.OutgoingWss;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.iface.Attachment;
import com.eviware.soapui.model.iface.Attachment.AttachmentEncoding;
import com.eviware.soapui.model.iface.MessagePart;
import com.eviware.soapui.model.iface.Operation;
import com.eviware.soapui.model.mock.MockRequest;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.settings.CommonSettings;
import com.eviware.soapui.settings.WsdlSettings;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.types.StringToStringsMap;
import com.eviware.soapui.support.xml.XmlUtils;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.log4j.Logger;
import org.apache.ws.security.WSSecurityException;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlException;
import org.w3c.dom.Document;
import javax.swing.ImageIcon;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Message;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* A WsdlMockResponse contained by a WsdlMockOperation
*
* @author ole.matzura
*/
public class WsdlMockResponse extends AbstractMockResponse<MockResponseConfig> implements WsaContainer {
private final static Logger log = Logger.getLogger(WsdlMockResponse.class);
public final static String MOCKRESULT_PROPERTY = WsdlMockResponse.class.getName() + "@mockresult";
public final static String HEADERS_PROPERTY = WsdlMockResponse.class.getName() + "@headers";
public final static String DISABLE_MULTIPART_ATTACHMENTS = WsdlMockResponse.class.getName()
+ "@disable-multipart-attachments";
public static final String FORCE_MTOM = WsdlMockResponse.class.getName() + "@force_mtom";
public static final String ENABLE_INLINE_FILES = WsdlMockResponse.class.getName() + "@enable_inline_files";
public final static String RESPONSE_DELAY_PROPERTY = WsdlMockResponse.class.getName() + "@response-delay";
public static final String STRIP_WHITESPACES = WsdlMockResponse.class.getName() + "@strip-whitespaces";
public static final String REMOVE_EMPTY_CONTENT = WsdlMockResponse.class.getName() + "@remove_empty_content";
public static final String ENCODE_ATTACHMENTS = WsdlMockResponse.class.getName() + "@encode_attachments";
public static final String OUGOING_WSS = WsdlMockResponse.class.getName() + "@outgoing-wss";
public static final String ICON_NAME = "/mockResponse.gif";
protected List<FileAttachment<WsdlMockResponse>> attachments = new ArrayList<FileAttachment<WsdlMockResponse>>();
private List<HttpAttachmentPart> definedAttachmentParts;
private IconAnimator<WsdlMockResponse> iconAnimator;
private WsaConfig wsaConfig;
public WsdlMockResponse(WsdlMockOperation operation, MockResponseConfig config) {
super(config, operation, ICON_NAME);
for (AttachmentConfig ac : getConfig().getAttachmentList()) {
attachments.add(new MockFileAttachment(ac, this));
}
if (!config.isSetEncoding()) {
config.setEncoding("UTF-8");
}
iconAnimator = new IconAnimator<WsdlMockResponse>(this, "/mockResponse.gif", "/exec_request.png", 4);
}
@Override
public void setConfig(MockResponseConfig config) {
super.setConfig(config);
if (wsaConfig != null) {
if (config.isSetWsaConfig()) {
wsaConfig.setConfig(config.getWsaConfig());
} else {
wsaConfig = null;
}
}
}
public Attachment[] getAttachments() {
return attachments.toArray(new Attachment[attachments.size()]);
}
protected String getContentType(Operation operation, String encoding) {
SoapVersion soapVersion = ((WsdlOperation) operation).getInterface().getSoapVersion();
return soapVersion.getContentTypeHttpHeader(encoding, null);
}
@Override
public ImageIcon getIcon() {
return iconAnimator.getIcon();
}
public WsdlMockOperation getMockOperation() {
return (WsdlMockOperation) getParent();
}
@Override
public String getScriptHelpUrl() {
return HelpUrls.MOCKRESPONSE_SCRIPT_HELP_URL;
}
public MessagePart[] getRequestParts() {
try {
List<MessagePart> result = new ArrayList<MessagePart>();
result.addAll(Arrays.asList(getMockOperation().getOperation().getDefaultRequestParts()));
if (getMockResult() != null) {
result.addAll(AttachmentUtils.extractAttachmentParts((WsdlOperation) getMockOperation().getOperation(), getMockResult()
.getMockRequest().getRequestContent(), true, false, isMtomEnabled()));
}
return result.toArray(new MessagePart[result.size()]);
} catch (Exception e) {
SoapUI.logError(e);
return new MessagePart[0];
}
}
public MessagePart[] getResponseParts() {
try {
// init
WsdlOperation op = (WsdlOperation) getMockOperation().getOperation();
if (op == null || op.isUnidirectional()) {
return new MessagePart[0];
}
List<MessagePart> result = new ArrayList<MessagePart>();
WsdlContext wsdlContext = op.getInterface().getWsdlContext();
BindingOperation bindingOperation = op.findBindingOperation(wsdlContext.getDefinition());
if (bindingOperation == null) {
return new MessagePart[0];
}
// header parts
BindingOutput bindingOutput = bindingOperation.getBindingOutput();
List<SoapHeader> headers = bindingOutput == null ? new ArrayList<SoapHeader>() : WsdlUtils
.getSoapHeaders(bindingOutput.getExtensibilityElements());
for (int i = 0; i < headers.size(); i++) {
SoapHeader header = headers.get(i);
Message message = wsdlContext.getDefinition().getMessage(header.getMessage());
if (message == null) {
log.error("Missing message for header: " + header.getMessage());
continue;
}
javax.wsdl.Part part = message.getPart(header.getPart());
if (part != null) {
SchemaType schemaType = WsdlUtils.getSchemaTypeForPart(wsdlContext, part);
SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart(wsdlContext, part);
if (schemaType != null) {
result.add(new WsdlHeaderPart(part.getName(), schemaType, part.getElementName(), schemaElement));
}
} else {
log.error("Missing part for header; " + header.getPart());
}
}
// content parts
javax.wsdl.Part[] parts = WsdlUtils.getOutputParts(bindingOperation);
for (int i = 0; i < parts.length; i++) {
javax.wsdl.Part part = parts[i];
if (!WsdlUtils.isAttachmentOutputPart(part, bindingOperation)) {
SchemaType schemaType = WsdlUtils.getSchemaTypeForPart(wsdlContext, part);
SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart(wsdlContext, part);
if (schemaType != null) {
result.add(new WsdlContentPart(part.getName(), schemaType, part.getElementName(), schemaElement));
}
}
}
result.addAll(Arrays.asList(getDefinedAttachmentParts()));
return result.toArray(new MessagePart[result.size()]);
} catch (Exception e) {
SoapUI.logError(e);
return new MessagePart[0];
}
}
public Attachment attachFile(File file, boolean cache) throws IOException {
FileAttachment<WsdlMockResponse> fileAttachment = new MockFileAttachment(file, cache, this);
attachments.add(fileAttachment);
notifyPropertyChanged(ATTACHMENTS_PROPERTY, null, fileAttachment);
return fileAttachment;
}
public int getAttachmentCount() {
return attachments.size();
}
public WsdlAttachment getAttachmentAt(int index) {
return attachments.get(index);
}
public void removeAttachment(Attachment attachment) {
int ix = attachments.indexOf(attachment);
attachments.remove(ix);
try {
notifyPropertyChanged(ATTACHMENTS_PROPERTY, attachment, null);
} finally {
getConfig().removeAttachment(ix);
}
}
public HttpAttachmentPart[] getDefinedAttachmentParts() {
if (definedAttachmentParts == null) {
try {
WsdlOperation operation = (WsdlOperation) getMockOperation().getOperation();
if (operation == null) {
definedAttachmentParts = new ArrayList<HttpAttachmentPart>();
} else {
UISupport.setHourglassCursor();
definedAttachmentParts = AttachmentUtils.extractAttachmentParts(operation, getResponseContent(), true,
true, isMtomEnabled());
}
} catch (Exception e) {
log.warn(e.toString());
} finally {
UISupport.resetCursor();
}
}
return definedAttachmentParts.toArray(new HttpAttachmentPart[definedAttachmentParts.size()]);
}
public HttpAttachmentPart getAttachmentPart(String partName) {
HttpAttachmentPart[] parts = getDefinedAttachmentParts();
for (HttpAttachmentPart part : parts) {
if (part.getName().equals(partName)) {
return part;
}
}
return null;
}
public Attachment[] getAttachmentsForPart(String partName) {
List<Attachment> result = new ArrayList<Attachment>();
for (Attachment attachment : attachments) {
if (attachment.getPart().equals(partName)) {
result.add(attachment);
}
}
return result.toArray(new Attachment[result.size()]);
}
@Override
public String getContentType() {
return getContentType(getOperation(), getEncoding());
}
public boolean isMtomEnabled() {
return getSettings().getBoolean(WsdlSettings.ENABLE_MTOM);
}
public void setMtomEnabled(boolean mtomEnabled) {
boolean old = isMtomEnabled();
getSettings().setBoolean(WsdlSettings.ENABLE_MTOM, mtomEnabled);
definedAttachmentParts = null;
notifyPropertyChanged(MTOM_NABLED_PROPERTY, old, mtomEnabled);
}
protected String executeSpecifics(MockRequest request, String responseContent, WsdlMockRunContext context) throws IOException, WSSecurityException {
if (this.getWsaConfig().isWsaEnabled()) {
WsdlOperation operation = getMockOperation().getOperation();
WsaUtils wsaUtils = new WsaUtils(responseContent, getSoapVersion(), operation, context);
responseContent = wsaUtils.addWSAddressingMockResponse(this, (WsdlMockRequest) request);
}
String outgoingWss = getOutgoingWss();
if (StringUtils.isNullOrEmpty(outgoingWss)) {
outgoingWss = getMockOperation().getMockService().getOutgoingWss();
}
if (StringUtils.hasContent(outgoingWss)) {
OutgoingWss outgoing = getMockOperation().getMockService().getProject().getWssContainer()
.getOutgoingWssByName(outgoingWss);
if (outgoing != null) {
Document dom = XmlUtils.parseXml(responseContent);
outgoing.processOutgoing(dom, context);
StringWriter writer = new StringWriter();
XmlUtils.serialize(dom, writer);
responseContent = writer.toString();
}
}
return responseContent;
}
@SuppressWarnings("unchecked")
public Attachment addAttachment(Attachment attachment) {
if (attachment instanceof BodyPartAttachment) {
try {
BodyPartAttachment att = (BodyPartAttachment) attachment;
AttachmentConfig newConfig = getConfig().addNewAttachment();
newConfig.setData(Tools.readAll(att.getInputStream(), 0).toByteArray());
newConfig.setContentId(att.getContentID());
newConfig.setContentType(att.getContentType());
newConfig.setName(att.getName());
FileAttachment<WsdlMockResponse> newAttachment = new MockFileAttachment(newConfig, this);
attachments.add(newAttachment);
return newAttachment;
} catch (Exception e) {
SoapUI.logError(e);
}
} else if (attachment instanceof FileAttachment) {
AttachmentConfig oldConfig = ((FileAttachment<WsdlMockResponse>) attachment).getConfig();
AttachmentConfig newConfig = (AttachmentConfig) getConfig().addNewAttachment().set(oldConfig);
FileAttachment<WsdlMockResponse> newAttachment = new MockFileAttachment(newConfig, this);
attachments.add(newAttachment);
return newAttachment;
}
return null;
}
public void setResponseDelay(long delay) {
long oldDelay = getResponseDelay();
if (delay == 0) {
getSettings().clearSetting(RESPONSE_DELAY_PROPERTY);
} else {
getSettings().setLong(RESPONSE_DELAY_PROPERTY, delay);
}
notifyPropertyChanged(RESPONSE_DELAY_PROPERTY, oldDelay, delay);
}
public long getResponseDelay() {
return getSettings().getLong(RESPONSE_DELAY_PROPERTY, 0);
}
public long getContentLength() {
return getResponseContent() == null ? 0 : getResponseContent().length();
}
public boolean isMultipartEnabled() {
return !getSettings().getBoolean(DISABLE_MULTIPART_ATTACHMENTS);
}
public void setMultipartEnabled(boolean multipartEnabled) {
getSettings().setBoolean(DISABLE_MULTIPART_ATTACHMENTS, multipartEnabled);
}
public void setEntitizeProperties(boolean entitizeProperties) {
getSettings().setBoolean(CommonSettings.ENTITIZE_PROPERTIES, entitizeProperties);
}
public boolean isForceMtom() {
return getSettings().getBoolean(FORCE_MTOM);
}
public void setForceMtom(boolean forceMtom) {
boolean old = getSettings().getBoolean(FORCE_MTOM);
getSettings().setBoolean(FORCE_MTOM, forceMtom);
notifyPropertyChanged(FORCE_MTOM, old, forceMtom);
}
protected String removeEmptyContent(String responseContent) {
if (isRemoveEmptyContent()) {
responseContent = RemoveEmptyContentRequestFilter.removeEmptyContent(responseContent, getSoapVersion()
.getEnvelopeNamespace(), true);
}
return responseContent;
}
@Override
public void setResponseContent(String responseContent) {
super.setResponseContent(responseContent);
handleFault(responseContent);
}
private void handleFault(String responseContent) {
try {
if (SoapUtils.isSoapFault(responseContent)) {
setResponseHttpStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
}
} catch (XmlException e) {
SoapUI.logError(e);
}
}
public boolean isRemoveEmptyContent() {
return getSettings().getBoolean(REMOVE_EMPTY_CONTENT);
}
public void setRemoveEmptyContent(boolean removeEmptyContent) {
boolean old = getSettings().getBoolean(REMOVE_EMPTY_CONTENT);
getSettings().setBoolean(REMOVE_EMPTY_CONTENT, removeEmptyContent);
notifyPropertyChanged(REMOVE_EMPTY_CONTENT, old, removeEmptyContent);
}
public boolean isEncodeAttachments() {
return getSettings().getBoolean(ENCODE_ATTACHMENTS);
}
public void setEncodeAttachments(boolean encodeAttachments) {
boolean old = getSettings().getBoolean(ENCODE_ATTACHMENTS);
getSettings().setBoolean(ENCODE_ATTACHMENTS, encodeAttachments);
notifyPropertyChanged(ENCODE_ATTACHMENTS, old, encodeAttachments);
}
public boolean isStripWhitespaces() {
return getSettings().getBoolean(STRIP_WHITESPACES);
}
public void setStripWhitespaces(boolean stripWhitespaces) {
boolean old = getSettings().getBoolean(STRIP_WHITESPACES);
getSettings().setBoolean(STRIP_WHITESPACES, stripWhitespaces);
notifyPropertyChanged(STRIP_WHITESPACES, old, stripWhitespaces);
}
public boolean isInlineFilesEnabled() {
return getSettings().getBoolean(WsdlMockResponse.ENABLE_INLINE_FILES);
}
public void setInlineFilesEnabled(boolean inlineFilesEnabled) {
getSettings().setBoolean(WsdlMockResponse.ENABLE_INLINE_FILES, inlineFilesEnabled);
}
@Override
public void beforeSave() {
super.beforeSave();
CompressedStringSupport.setString(getConfig().getResponseContent(), getResponseContent());
}
public void addAttachmentsChangeListener(PropertyChangeListener listener) {
addPropertyChangeListener(ATTACHMENTS_PROPERTY, listener);
}
public boolean isReadOnly() {
return false;
}
public void removeAttachmentsChangeListener(PropertyChangeListener listener) {
removePropertyChangeListener(ATTACHMENTS_PROPERTY, listener);
}
public SoapVersion getSoapVersion() {
if( getMockOperation().getOperation() == null ) {
return SoapVersion.Soap11;
}
return getMockOperation().getOperation().getInterface().getSoapVersion();
}
public PropertyExpansion[] getPropertyExpansions() {
List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(this, this, "responseContent"));
StringToStringsMap responseHeaders = getResponseHeaders();
for (Map.Entry<String, List<String>> headerEntry : responseHeaders.entrySet()) {
for (String value : headerEntry.getValue()) {
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(this,
new ResponseHeaderHolder(headerEntry.getKey(), value, this), "value"));
}
}
addWsaPropertyExpansions(result, getWsaConfig(), this);
return result.toArray(new PropertyExpansion[result.size()]);
}
public void addWsaPropertyExpansions(List<PropertyExpansion> result, WsaConfig wsaConfig, ModelItem modelItem) {
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "action"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "from"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "to"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "replyTo"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "replyToRefParams"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "faultTo"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "faultToRefParams"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "relatesTo"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "relationshipType"));
result.addAll(PropertyExpansionUtils.extractPropertyExpansions(modelItem, wsaConfig, "messageID"));
}
public static class ResponseHeaderHolder {
private final String key;
private final String oldValue;
private WsdlMockResponse mockResponse;
public ResponseHeaderHolder(String key, String oldValue, WsdlMockResponse mockResponse) {
this.key = key;
this.oldValue = oldValue;
this.mockResponse = mockResponse;
}
public String getValue() {
return oldValue;
}
public void setValue(String value) {
StringToStringsMap valueMap = mockResponse.getResponseHeaders();
valueMap.replace(key, oldValue, value);
mockResponse.setResponseHeaders(valueMap);
}
}
public String getOutgoingWss() {
return getConfig().getOutgoingWss();
}
public void setOutgoingWss(String outgoingWss) {
String old = getOutgoingWss();
getConfig().setOutgoingWss(outgoingWss);
notifyPropertyChanged(OUGOING_WSS, old, outgoingWss);
}
public String getPropertiesLabel() {
return "Custom Properties";
}
public AttachmentEncoding getAttachmentEncoding(String partName) {
HttpAttachmentPart attachmentPart = getAttachmentPart(partName);
if (attachmentPart == null) {
return AttachmentUtils.getAttachmentEncoding(getOperation(), partName, true);
} else {
return AttachmentUtils.getAttachmentEncoding(getOperation(), attachmentPart, true);
}
}
public WsaConfig getWsaConfig() {
if (wsaConfig == null) {
if (!getConfig().isSetWsaConfig()) {
getConfig().addNewWsaConfig();
}
wsaConfig = new WsaConfig(getConfig().getWsaConfig(), this);
// wsaConfig.setGenerateMessageId(true);
}
return wsaConfig;
}
public boolean isWsAddressing() {
return getConfig().getUseWsAddressing();
}
public void setWsAddressing(boolean wsAddressing) {
boolean old = getConfig().getUseWsAddressing();
getConfig().setUseWsAddressing(wsAddressing);
notifyPropertyChanged("wsAddressing", old, wsAddressing);
}
public boolean isWsaEnabled() {
return isWsAddressing();
}
public void setWsaEnabled(boolean arg0) {
setWsAddressing(arg0);
}
public WsdlOperation getOperation() {
return ((WsdlMockOperation) getMockOperation()).getOperation();
}
public void setOperation(WsdlOperation operation) {
((WsdlMockOperation) getMockOperation()).setOperation(operation);
}
protected String mockresultProperty() {
return MOCKRESULT_PROPERTY;
}
}