/*
* 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;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.TestStepConfig;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
import com.eviware.soapui.model.support.DefaultTestStepProperty;
import com.eviware.soapui.model.support.TestStepBeanProperty;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestRunner.Status;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
import com.eviware.soapui.support.GroovyUtils;
import com.eviware.soapui.support.UISupport;
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 org.apache.log4j.Logger;
import javax.swing.ImageIcon;
import static com.eviware.soapui.impl.wsdl.teststeps.Script.RESULT_PROPERTY;
import static com.eviware.soapui.impl.wsdl.teststeps.Script.SCRIPT_PROPERTY;
/**
* TestStep that executes an arbitrary Groovy script
*
* @author ole.matzura
*/
public class WsdlGroovyScriptTestStep extends WsdlTestStepWithProperties implements PropertyExpansionContainer {
private final static Logger logger = Logger.getLogger("groovy.log");
private String scriptText = "";
private Object scriptResult;
private ImageIcon failedIcon;
private ImageIcon okIcon;
private SoapUIScriptEngine scriptEngine;
public WsdlGroovyScriptTestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest) {
super(testCase, config, true, forLoadTest);
if (!forLoadTest) {
okIcon = UISupport.createImageIcon("/groovy_script_step.png");
setIcon(okIcon);
failedIcon = UISupport.createImageIcon("/failed_groovy_step.png");
}
if (config.getConfig() == null) {
if (!forLoadTest) {
saveScript(config);
}
} else {
readConfig(config);
}
addProperty(new DefaultTestStepProperty(RESULT_PROPERTY, true, new DefaultTestStepProperty.PropertyHandlerAdapter() {
public String getValue(DefaultTestStepProperty property) {
return scriptResult == null ? null : scriptResult.toString();
}
}, this));
addProperty(new TestStepBeanProperty(SCRIPT_PROPERTY, false, this, SCRIPT_PROPERTY, this));
scriptEngine = SoapUIScriptEngineRegistry.create(this);
scriptEngine.setScript(getScript());
if (forLoadTest && !isDisabled()) {
try {
scriptEngine.compile();
} catch (Exception e) {
SoapUI.logError(e);
}
}
}
public Logger getLogger() {
SoapUI.ensureGroovyLog();
return logger;
}
private void readConfig(TestStepConfig config) {
XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader(config.getConfig());
scriptText = reader.readString(SCRIPT_PROPERTY, "");
}
private void saveScript(TestStepConfig config) {
XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
builder.add(SCRIPT_PROPERTY, scriptText);
config.setConfig(builder.finish());
}
public void resetConfigOnMove(TestStepConfig config) {
super.resetConfigOnMove(config);
readConfig(config);
}
public String getDefaultSourcePropertyName() {
return RESULT_PROPERTY;
}
public TestStepResult run(TestCaseRunner testRunner, TestCaseRunContext context) {
SoapUI.ensureGroovyLog();
WsdlTestStepResult result = new WsdlTestStepResult(this);
Logger log = (Logger) context.getProperty("log");
if (log == null) {
log = logger;
} else {
log.addAppender(logger.getAppender("GLOBAL_GROOVY_LOG"));
}
try {
if (scriptText.trim().length() > 0) {
synchronized (this) {
scriptEngine.setVariable("context", context);
scriptEngine.setVariable("testRunner", testRunner);
scriptEngine.setVariable("log", log);
result.setTimeStamp(System.currentTimeMillis());
result.startTimer();
scriptResult = scriptEngine.run();
result.stopTimer();
if (scriptResult != null) {
result.addMessage("Script-result: " + scriptResult.toString());
// FIXME The property should not me hard coded
firePropertyValueChanged(RESULT_PROPERTY, null, String.valueOf(result));
}
}
}
// testRunner status may have been changed by script..
Status testRunnerStatus = testRunner.getStatus();
if (testRunnerStatus == Status.FAILED) {
result.setStatus(TestStepStatus.FAILED);
} else if (testRunnerStatus == Status.CANCELED) {
result.setStatus(TestStepStatus.CANCELED);
} else {
result.setStatus(TestStepStatus.OK);
}
} catch (Throwable e) {
String errorLineNumber = GroovyUtils.extractErrorLineNumber(e);
SoapUI.logError(e);
result.stopTimer();
result.addMessage(e.toString());
if (errorLineNumber != null) {
result.addMessage("error at line: " + errorLineNumber);
}
result.setError(e);
result.setStatus(TestStepStatus.FAILED);
} finally {
if (!isForLoadTest()) {
setIcon(result.getStatus() == TestStepStatus.FAILED ? failedIcon : okIcon);
}
if (scriptEngine != null) {
scriptEngine.clearVariables();
}
}
return result;
}
public String getScript() {
return scriptText;
}
public void setScript(String scriptText) {
if (scriptText.equals(this.scriptText)) {
return;
}
String oldScript = this.scriptText;
this.scriptText = scriptText;
scriptEngine.setScript(scriptText);
saveScript(getConfig());
notifyPropertyChanged(SCRIPT_PROPERTY, oldScript, scriptText);
}
@Override
public void release() {
super.release();
scriptEngine.release();
}
public PropertyExpansion[] getPropertyExpansions() {
PropertyExpansionsResult result = new PropertyExpansionsResult(this);
result.extractAndAddAll(SCRIPT_PROPERTY);
return result.toArray();
}
}