/*
* 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.support.scripting.groovy;
import com.eviware.soapui.SoapUIExtensionClassLoader;
import com.eviware.soapui.SoapUIExtensionClassLoader.SoapUIClassLoaderState;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilerConfiguration;
/**
* A Groovy ScriptEngine
*
* @author ole.matzura
*/
public class SoapUIGroovyScriptEngine implements SoapUIScriptEngine {
private GroovyClassLoader classLoader;
private GroovyShell shell;
private Binding binding;
private Script script;
private String scriptText;
protected ScriptSaver saver = new ScriptSaver();
public SoapUIGroovyScriptEngine(ClassLoader parentClassLoader) {
classLoader = new GroovyClassLoader(parentClassLoader);
binding = new Binding();
CompilerConfiguration config = new CompilerConfiguration();
config.setDebug(true);
config.setVerbose(true);
shell = new GroovyShell(classLoader, binding, config);
}
protected class ScriptSaver {
private String text = null;
private boolean locked = false;
public synchronized void save(String scriptText) {
if (locked) {
text = scriptText;
} else {
synchronizedSetScript(scriptText);
}
}
public synchronized void lockSave() {
locked = true;
}
public synchronized void unlockSave() {
if (text != null) {
synchronizedSetScript(text);
text = null;
}
locked = false;
}
}
public synchronized Object run() throws Exception {
saver.lockSave();
SoapUIClassLoaderState state = SoapUIExtensionClassLoader.ensure();
try {
if (StringUtils.isNullOrEmpty(scriptText)) {
return null;
}
if (script == null) {
compile();
}
Object result = script.run();
return result;
} finally {
state.restore();
saver.unlockSave();
}
}
protected synchronized void synchronizedSetScript(String scriptText) {
if (scriptText != null && scriptText.equals(this.scriptText)) {
return;
}
if (script != null) {
script.setBinding(null);
script = null;
if (shell != null) {
shell.resetLoadedClasses();
}
classLoader.clearCache();
}
this.scriptText = scriptText;
}
public synchronized void setScript(String scriptText) {
if (scriptText != null && !scriptText.equals(this.scriptText)) {
saver.save(scriptText);
}
}
protected synchronized void reset() {
saver.lockSave();
script = null;
saver.unlockSave();
}
public synchronized void compile() throws Exception {
if (script == null) {
SoapUIClassLoaderState state = SoapUIExtensionClassLoader.ensure();
try {
script = shell.parse(scriptText);
script.setBinding(binding);
} finally {
state.restore();
}
}
}
public synchronized void setVariable(String name, Object value) {
binding.setVariable(name, value);
}
public synchronized void clearVariables() {
if (binding != null) {
binding.getVariables().clear();
}
}
public synchronized void release() {
script = null;
if (binding != null) {
binding.getVariables().clear();
binding = null;
}
if (shell != null) {
shell.resetLoadedClasses();
shell = null;
}
}
protected Binding getBinding() {
return binding;
}
protected GroovyClassLoader getClassLoader() {
return classLoader;
}
protected Script getScript() {
return script;
}
protected String getScriptText() {
return scriptText;
}
protected GroovyShell getShell() {
return shell;
}
}