/*
* 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.teststeps.assertions.basic;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.TestAssertionConfig;
import com.eviware.soapui.impl.rest.RestRequestInterface;
import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
import com.eviware.soapui.impl.wsdl.panels.assertions.AssertionCategoryMapping;
import com.eviware.soapui.impl.wsdl.panels.assertions.AssertionListEntry;
import com.eviware.soapui.impl.wsdl.panels.mockoperation.WsdlMockResponseMessageExchange;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.support.JdbcMessageExchange;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
import com.eviware.soapui.impl.wsdl.teststeps.HttpResponseMessageExchange;
import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequestStepInterface;
import com.eviware.soapui.impl.wsdl.teststeps.JdbcRequestTestStep;
import com.eviware.soapui.impl.wsdl.teststeps.RestResponseMessageExchange;
import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStepInterface;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlMockResponseTestStep;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlResponseMessageExchange;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
import com.eviware.soapui.impl.wsdl.teststeps.assertions.AbstractTestAssertionFactory;
import com.eviware.soapui.model.TestPropertyHolder;
import com.eviware.soapui.model.iface.MessageExchange;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.testsuite.Assertable;
import com.eviware.soapui.model.testsuite.AssertionError;
import com.eviware.soapui.model.testsuite.AssertionException;
import com.eviware.soapui.model.testsuite.RequestAssertion;
import com.eviware.soapui.model.testsuite.ResponseAssertion;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.log.JLogList;
import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
import com.jgoodies.forms.builder.ButtonBarBuilder;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.XmlObject;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* Assertion performed by a custom Grooy Script
*
* @author ole.matzura
*/
public class GroovyScriptAssertion extends WsdlMessageAssertion implements RequestAssertion, ResponseAssertion {
public static final String ID = "GroovyScriptAssertion";
public static final String LABEL = "Script Assertion";
public static final String DESCRIPTION = "Runs a custom script to perform arbitrary validations. Applicable to any Property.";
private String scriptText;
private SoapUIScriptEngine scriptEngine;
private JDialog dialog;
private GroovyScriptAssertionPanel groovyScriptAssertionPanel;
private String oldScriptText;
public GroovyScriptAssertion(TestAssertionConfig assertionConfig, Assertable modelItem) {
super(assertionConfig, modelItem, true, true, true, false);
XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader(getConfiguration());
scriptText = reader.readString("scriptText", "");
scriptEngine = SoapUIScriptEngineRegistry.create(this);
scriptEngine.setScript(scriptText);
}
@Override
protected String internalAssertRequest(MessageExchange messageExchange, SubmitContext context)
throws AssertionException {
return assertScript(messageExchange, context, SoapUI.ensureGroovyLog());
}
private String assertScript(MessageExchange messageExchange, SubmitContext context, Logger log)
throws AssertionException {
try {
scriptEngine.setVariable("context", context);
scriptEngine.setVariable("messageExchange", messageExchange);
scriptEngine.setVariable("log", log);
scriptEngine.setVariable("assertion", this);
Object result = scriptEngine.run();
return result == null ? null : result.toString();
} catch (Throwable e) {
throw new AssertionException(new AssertionError(e.getMessage()));
} finally {
scriptEngine.clearVariables();
}
}
@Override
protected String internalAssertResponse(MessageExchange messageExchange, SubmitContext context)
throws AssertionException {
return assertScript(messageExchange, context, SoapUI.ensureGroovyLog());
}
@Override
protected String internalAssertProperty(TestPropertyHolder source, String propertyName,
MessageExchange messageExchange, SubmitContext context) throws AssertionException {
return null;
}
@Override
public boolean configure() {
if (dialog == null) {
buildDialog();
}
oldScriptText = scriptText;
UISupport.showDialog(dialog);
return true;
}
protected void buildDialog() {
dialog = new JDialog(UISupport.getMainFrame(), "Script Assertion", true);
groovyScriptAssertionPanel = new GroovyScriptAssertionPanel();
dialog.setContentPane(groovyScriptAssertionPanel);
UISupport.initDialogActions(dialog, groovyScriptAssertionPanel.getShowOnlineHelpAction(),
groovyScriptAssertionPanel.getDefaultButton());
dialog.setSize(600, 500);
dialog.setModal(true);
dialog.pack();
}
protected GroovyScriptAssertionPanel getScriptAssertionPanel() {
return groovyScriptAssertionPanel;
}
protected XmlObject createConfiguration() {
XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
builder.add("scriptText", scriptText);
return builder.finish();
}
public String getScriptText() {
return scriptText;
}
public void setScriptText(String scriptText) {
this.scriptText = scriptText;
scriptEngine.setScript(scriptText);
setConfiguration(createConfiguration());
}
@Override
public void release() {
super.release();
scriptEngine.release();
if (groovyScriptAssertionPanel != null) {
groovyScriptAssertionPanel.release();
}
}
public static class Factory extends AbstractTestAssertionFactory {
public Factory() {
super(GroovyScriptAssertion.ID, GroovyScriptAssertion.LABEL, GroovyScriptAssertion.class);
}
@Override
public String getCategory() {
return AssertionCategoryMapping.SCRIPT_CATEGORY;
}
@Override
public Class<? extends WsdlMessageAssertion> getAssertionClassType() {
return GroovyScriptAssertion.class;
}
@Override
public AssertionListEntry getAssertionListEntry() {
return new AssertionListEntry(GroovyScriptAssertion.ID, GroovyScriptAssertion.LABEL,
GroovyScriptAssertion.DESCRIPTION);
}
}
protected class GroovyScriptAssertionPanel extends JPanel {
private GroovyEditor editor;
private JSplitPane mainSplit;
private JLogList logArea;
private RunAction runAction = new RunAction();
private Logger logger;
private JButton okButton;
private ShowOnlineHelpAction showOnlineHelpAction;
public GroovyScriptAssertionPanel() {
super(new BorderLayout());
buildUI();
setPreferredSize(new Dimension(600, 440));
logger = Logger.getLogger("ScriptAssertion." + getName());
editor.requestFocusInWindow();
}
public GroovyEditor getGroovyEditor() {
return editor;
}
public void release() {
editor.release();
logger = null;
}
private void buildUI() {
editor = new GroovyEditor(new ScriptStepGroovyEditorModel());
logArea = new JLogList("Groovy Test Log");
logArea.addLogger("ScriptAssertion." + getName(), true);
logArea.getLogList().addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() < 2) {
return;
}
String value = logArea.getLogList().getSelectedValue().toString();
if (value == null) {
return;
}
editor.selectError(value);
}
});
editor.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3),
editor.getBorder()));
mainSplit = UISupport.createVerticalSplit(editor, logArea);
mainSplit.setDividerLocation(280);
mainSplit.setResizeWeight(0.8);
add(mainSplit, BorderLayout.CENTER);
add(buildToolbar(), BorderLayout.NORTH);
add(buildStatusBar(), BorderLayout.SOUTH);
}
public JButton getDefaultButton() {
return okButton;
}
public ShowOnlineHelpAction getShowOnlineHelpAction() {
return showOnlineHelpAction;
}
private Component buildStatusBar() {
ButtonBarBuilder builder = new ButtonBarBuilder();
showOnlineHelpAction = new ShowOnlineHelpAction(HelpUrls.GROOVYASSERTION_HELP_URL);
builder.addFixed(UISupport.createToolbarButton(showOnlineHelpAction));
builder.addGlue();
okButton = new JButton(new OkAction());
builder.addFixed(okButton);
builder.addRelatedGap();
builder.addFixed(new JButton(new CancelAction()));
builder.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3));
return builder.getPanel();
}
private JComponent buildToolbar() {
JXToolBar toolBar = UISupport.createToolbar();
JButton runButton = UISupport.createToolbarButton(runAction);
toolBar.add(runButton);
toolBar.add(Box.createHorizontalGlue());
JLabel label = new JLabel("<html>Script is invoked with <code>log</code>, <code>context</code> "
+ "and <code>messageExchange</code> variables</html>");
label.setToolTipText(label.getText());
label.setMaximumSize(label.getPreferredSize());
toolBar.addFixed(label);
toolBar.addSpace(3);
return toolBar;
}
private final class OkAction extends AbstractAction {
public OkAction() {
super("OK");
}
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
setScriptText(editor.getEditArea().getText());
}
}
private final class CancelAction extends AbstractAction {
public CancelAction() {
super("Cancel");
}
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
editor.getEditArea().setText(oldScriptText);
}
}
private class ScriptStepGroovyEditorModel extends AbstractGroovyEditorModel {
public ScriptStepGroovyEditorModel() {
super(new String[]{"log", "context", "messageExchange"}, getAssertable().getModelItem(), "Assertion");
}
public Action getRunAction() {
return runAction;
}
public String getScript() {
return getScriptText();
}
public void setScript(String text) {
}
}
private class RunAction extends AbstractAction {
public RunAction() {
putValue(Action.SMALL_ICON, UISupport.createImageIcon("/run.png"));
putValue(Action.SHORT_DESCRIPTION,
"Runs this assertion script against the last messageExchange with a mock testContext");
}
public void actionPerformed(ActionEvent event) {
TestStep testStep = getAssertable().getTestStep();
MessageExchange exchange = null;
if (testStep instanceof WsdlTestRequestStep) {
exchange = new WsdlResponseMessageExchange(((WsdlTestRequestStep) testStep).getTestRequest());
} else if (testStep instanceof RestTestRequestStepInterface) {
exchange = new RestResponseMessageExchange(((RestRequestInterface) ((RestTestRequestStepInterface) testStep).getTestRequest()));
} else if (testStep instanceof HttpTestRequestStepInterface) {
exchange = new HttpResponseMessageExchange(((HttpTestRequestStepInterface) testStep).getTestRequest());
} else if (testStep instanceof WsdlMockResponseTestStep) {
exchange = new WsdlMockResponseMessageExchange(((WsdlMockResponseTestStep) testStep).getMockResponse());
} else if (testStep instanceof JdbcRequestTestStep) {
JdbcRequestTestStep jdbcRequestTestStep = (JdbcRequestTestStep) testStep;
exchange = new JdbcMessageExchange(jdbcRequestTestStep, jdbcRequestTestStep.getJdbcRequest().getResponse());
}
try {
Logger groovyLog = SoapUI.ensureGroovyLog();
logger.addAppender(groovyLog.getAppender("GLOBAL_GROOVY_LOG"));
try {
setScriptText(editor.getEditArea().getText());
String result = assertScript(exchange, new WsdlTestRunContext(testStep), logger);
UISupport.showInfoMessage("Script Assertion Passed" + ((result == null) ? "" : ": [" + result + "]"));
} finally {
logger.removeAppender("GLOBAL_GROOVY_LOG");
}
} catch (AssertionException e) {
UISupport.showErrorMessage(e.getMessage());
} catch (Exception e) {
SoapUI.logError(e);
UISupport.showErrorMessage(e.getMessage());
}
editor.requestFocusInWindow();
}
}
}
}