/*
* 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.panels.teststeps;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunContext;
import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunner;
import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditorModel;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStepResult;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.settings.Settings;
import com.eviware.soapui.model.settings.SettingsListener;
import com.eviware.soapui.support.ListDataChangeListener;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.JComponentInspector;
import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
import com.eviware.soapui.support.components.JInspectorPanel;
import com.eviware.soapui.support.components.JInspectorPanelFactory;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.log.JLogList;
import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.ListModel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import static com.eviware.soapui.impl.wsdl.teststeps.Script.SCRIPT_PROPERTY;
/**
* DesktopPanel for WsdlGroovyTestSteps
*
* @author Ole.Matzura
*/
public class GroovyScriptStepDesktopPanel extends ModelItemDesktopPanel<WsdlGroovyScriptTestStep> implements
PropertyChangeListener {
private final WsdlGroovyScriptTestStep groovyStep;
private GroovyEditor editor;
private JLogList logArea;
private Logger logger;
private TestRunComponentEnabler componentEnabler;
private RunAction runAction = new RunAction();
private JEditorStatusBarWithProgress statusBar;
private SettingsListener settingsListener;
private JComponentInspector<JComponent> logInspector;
public boolean updating;
private JInspectorPanel inspectorPanel;
public GroovyScriptStepDesktopPanel(WsdlGroovyScriptTestStep groovyStep) {
super(groovyStep);
this.groovyStep = groovyStep;
componentEnabler = new TestRunComponentEnabler(groovyStep.getTestCase());
buildUI();
setPreferredSize(new Dimension(600, 440));
logger = Logger.getLogger(groovyStep.getName() + "#" + hashCode());
addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
editor.requestFocusInWindow();
}
});
groovyStep.addPropertyChangeListener(this);
}
protected GroovyEditor getEditor() {
return editor;
}
private void buildUI() {
editor = new GroovyEditor(new ScriptStepGroovyEditorModel());
logArea = new JLogList("Groovy Test Log");
logArea.addLogger(groovyStep.getName() + "#" + hashCode(), 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);
}
});
logArea.getLogList().getModel().addListDataListener(new ListDataChangeListener() {
@Override
public void dataChanged(ListModel model) {
logInspector.setTitle("Log Output (" + model.getSize() + ")");
}
});
inspectorPanel = JInspectorPanelFactory.build(editor);
logInspector = inspectorPanel.addInspector(new JComponentInspector<JComponent>(logArea, "Log Output (0)",
"Groovy Log output for this script", true));
inspectorPanel.setDefaultDividerLocation(0.8F);
inspectorPanel.activate(logInspector);
add(inspectorPanel.getComponent(), BorderLayout.CENTER);
add(buildToolbar(), BorderLayout.NORTH);
add(buildStatusBar(), BorderLayout.SOUTH);
componentEnabler.add(editor);
}
private Component buildStatusBar() {
statusBar = new JEditorStatusBarWithProgress(editor);
return statusBar;
}
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>testRunner</code> variables</html>");
label.setToolTipText(label.getText());
label.setMaximumSize(label.getPreferredSize());
toolBar.add(label);
toolBar.addRelatedGap();
toolBar.add(UISupport.createToolbarButton(new ShowOnlineHelpAction(HelpUrls.GROOVYSTEPEDITOR_HELP_URL)));
componentEnabler.add(runButton);
return toolBar;
}
public boolean onClose(boolean canCancel) {
componentEnabler.release();
editor.release();
SoapUI.getSettings().removeSettingsListener(settingsListener);
logger.removeAllAppenders();
logger = null;
inspectorPanel.release();
getModelItem().removePropertyChangeListener(this);
return super.release();
}
public JComponent getComponent() {
return this;
}
public boolean dependsOn(ModelItem modelItem) {
return modelItem == groovyStep || modelItem == groovyStep.getTestCase()
|| modelItem == groovyStep.getTestCase().getTestSuite()
|| modelItem == groovyStep.getTestCase().getTestSuite().getProject();
}
private class ScriptStepGroovyEditorModel implements GroovyEditorModel {
public String[] getKeywords() {
return new String[]{"log", "context", "testRunner"};
}
public Action getRunAction() {
return runAction;
}
public String getScript() {
return groovyStep.getScript();
}
public void setScript(String text) {
if (updating) {
return;
}
updating = true;
groovyStep.setScript(text);
updating = false;
}
public Settings getSettings() {
return SoapUI.getSettings();
}
public String getScriptName() {
return null;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
public ModelItem getModelItem() {
return groovyStep;
}
}
private class RunAction extends AbstractAction {
public RunAction() {
putValue(Action.SMALL_ICON, UISupport.createImageIcon("/run.png"));
putValue(Action.SHORT_DESCRIPTION,
"Runs this script in a seperate thread using a mock testRunner and testContext");
}
public void actionPerformed(ActionEvent e) {
SoapUI.getThreadPool().execute(new Runnable() {
public void run() {
MockTestRunner mockTestRunner = new MockTestRunner(groovyStep.getTestCase(), logger);
statusBar.setIndeterminate(true);
WsdlTestStepResult result = (WsdlTestStepResult) groovyStep.run(mockTestRunner,
new MockTestRunContext(mockTestRunner, groovyStep));
statusBar.setIndeterminate(false);
Throwable er = result.getError();
if (er != null) {
String message = er.getMessage();
// ugly...
editor.selectError(message);
UISupport.showErrorMessage(StringUtils.join(result.getMessages(), "\n"));
editor.requestFocus();
} else if (result.getMessages().length > 0) {
UISupport.showInfoMessage(StringUtils.join(result.getMessages(), "\n"));
}
}
});
}
}
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(SCRIPT_PROPERTY) && !updating) {
updating = true;
editor.getEditArea().setText((String) evt.getNewValue());
updating = false;
}
super.propertyChange(evt);
}
}