View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.teststeps;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.FocusAdapter;
20  import java.awt.event.FocusEvent;
21  import java.awt.event.MouseAdapter;
22  import java.awt.event.MouseEvent;
23  import java.beans.PropertyChangeEvent;
24  import java.beans.PropertyChangeListener;
25  
26  import javax.swing.AbstractAction;
27  import javax.swing.Action;
28  import javax.swing.Box;
29  import javax.swing.JButton;
30  import javax.swing.JComponent;
31  import javax.swing.JLabel;
32  import javax.swing.ListModel;
33  
34  import org.apache.commons.lang.StringUtils;
35  import org.apache.log4j.Logger;
36  
37  import com.eviware.soapui.SoapUI;
38  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
39  import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunContext;
40  import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunner;
41  import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
42  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
43  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditorModel;
44  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
45  import com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep;
46  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStepResult;
47  import com.eviware.soapui.model.ModelItem;
48  import com.eviware.soapui.model.settings.Settings;
49  import com.eviware.soapui.model.settings.SettingsListener;
50  import com.eviware.soapui.support.ListDataChangeListener;
51  import com.eviware.soapui.support.UISupport;
52  import com.eviware.soapui.support.components.JComponentInspector;
53  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
54  import com.eviware.soapui.support.components.JInspectorPanel;
55  import com.eviware.soapui.support.components.JInspectorPanelFactory;
56  import com.eviware.soapui.support.components.JXToolBar;
57  import com.eviware.soapui.support.log.JLogList;
58  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
59  
60  /***
61   * DesktopPanel for WsdlGroovyTestSteps
62   * 
63   * @author Ole.Matzura
64   */
65  
66  public class GroovyScriptStepDesktopPanel extends ModelItemDesktopPanel<WsdlGroovyScriptTestStep> implements
67  		PropertyChangeListener
68  {
69  	private final WsdlGroovyScriptTestStep groovyStep;
70  	private GroovyEditor editor;
71  	private JLogList logArea;
72  	private Logger logger;
73  	private TestRunComponentEnabler componentEnabler;
74  	private RunAction runAction = new RunAction();
75  	private JEditorStatusBarWithProgress statusBar;
76  	private SettingsListener settingsListener;
77  	private JComponentInspector<JComponent> logInspector;
78  	public boolean updating;
79  	private JInspectorPanel inspectorPanel;
80  
81  	public GroovyScriptStepDesktopPanel( WsdlGroovyScriptTestStep groovyStep )
82  	{
83  		super( groovyStep );
84  		this.groovyStep = groovyStep;
85  		componentEnabler = new TestRunComponentEnabler( groovyStep.getTestCase() );
86  
87  		buildUI();
88  		setPreferredSize( new Dimension( 600, 440 ) );
89  
90  		logger = Logger.getLogger( groovyStep.getName() + "#" + hashCode() );
91  
92  		addFocusListener( new FocusAdapter()
93  		{
94  			public void focusGained( FocusEvent e )
95  			{
96  				editor.requestFocusInWindow();
97  			}
98  		} );
99  
100 		groovyStep.addPropertyChangeListener( this );
101 	}
102 
103 	protected GroovyEditor getEditor()
104 	{
105 		return editor;
106 	}
107 
108 	private void buildUI()
109 	{
110 		editor = new GroovyEditor( new ScriptStepGroovyEditorModel() );
111 
112 		logArea = new JLogList( "Groovy Test Log" );
113 		logArea.addLogger( groovyStep.getName() + "#" + hashCode(), true );
114 		logArea.getLogList().addMouseListener( new MouseAdapter()
115 		{
116 
117 			public void mouseClicked( MouseEvent e )
118 			{
119 				if( e.getClickCount() < 2 )
120 					return;
121 
122 				String value = logArea.getLogList().getSelectedValue().toString();
123 				if( value == null )
124 					return;
125 
126 				editor.selectError( value );
127 			}
128 		} );
129 
130 		logArea.getLogList().getModel().addListDataListener( new ListDataChangeListener()
131 		{
132 
133 			@Override
134 			public void dataChanged( ListModel model )
135 			{
136 				logInspector.setTitle( "Log Output (" + model.getSize() + ")" );
137 
138 			}
139 		} );
140 
141 		inspectorPanel = JInspectorPanelFactory.build( editor );
142 		logInspector = inspectorPanel.addInspector( new JComponentInspector<JComponent>( logArea, "Log Output (0)",
143 				"Groovy Log output for this script", true ) );
144 		inspectorPanel.setDefaultDividerLocation( 0.8F );
145 		inspectorPanel.activate( logInspector );
146 		add( inspectorPanel.getComponent(), BorderLayout.CENTER );
147 		add( buildToolbar(), BorderLayout.NORTH );
148 		add( buildStatusBar(), BorderLayout.SOUTH );
149 
150 		componentEnabler.add( editor );
151 	}
152 
153 	private Component buildStatusBar()
154 	{
155 		statusBar = new JEditorStatusBarWithProgress( editor );
156 		return statusBar;
157 	}
158 
159 	private JComponent buildToolbar()
160 	{
161 		JXToolBar toolBar = UISupport.createToolbar();
162 		JButton runButton = UISupport.createToolbarButton( runAction );
163 		toolBar.add( runButton );
164 		toolBar.add( Box.createHorizontalGlue() );
165 		JLabel label = new JLabel( "<html>Script is invoked with <code>log</code>, <code>context</code> "
166 				+ "and <code>testRunner</code> variables</html>" );
167 		label.setToolTipText( label.getText() );
168 		label.setMaximumSize( label.getPreferredSize() );
169 
170 		toolBar.add( label );
171 		toolBar.addRelatedGap();
172 		toolBar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.GROOVYSTEPEDITOR_HELP_URL ) ) );
173 
174 		componentEnabler.add( runButton );
175 
176 		return toolBar;
177 	}
178 
179 	public boolean onClose( boolean canCancel )
180 	{
181 		componentEnabler.release();
182 		editor.release();
183 		SoapUI.getSettings().removeSettingsListener( settingsListener );
184 		logger.removeAllAppenders();
185 		logger = null;
186 		logArea.release();
187 		inspectorPanel.release();
188 		
189 		getModelItem().removePropertyChangeListener( this );
190 		
191 		return super.release();
192 	}
193 
194 	public JComponent getComponent()
195 	{
196 		return this;
197 	}
198 
199 	public boolean dependsOn( ModelItem modelItem )
200 	{
201 		return modelItem == groovyStep || modelItem == groovyStep.getTestCase()
202 				|| modelItem == groovyStep.getTestCase().getTestSuite()
203 				|| modelItem == groovyStep.getTestCase().getTestSuite().getProject();
204 	}
205 
206 	private class ScriptStepGroovyEditorModel implements GroovyEditorModel
207 	{
208 		public String[] getKeywords()
209 		{
210 			return new String[] { "log", "context", "testRunner" };
211 		}
212 
213 		public Action getRunAction()
214 		{
215 			return runAction;
216 		}
217 
218 		public String getScript()
219 		{
220 			return groovyStep.getScript();
221 		}
222 
223 		public void setScript( String text )
224 		{
225 			if( updating )
226 				return;
227 
228 			updating = true;
229 			groovyStep.setScript( text );
230 			updating = false;
231 		}
232 
233 		public Settings getSettings()
234 		{
235 			return SoapUI.getSettings();
236 		}
237 
238 		public String getScriptName()
239 		{
240 			return null;
241 		}
242 
243 		public void addPropertyChangeListener( PropertyChangeListener listener )
244 		{
245 		}
246 
247 		public void removePropertyChangeListener( PropertyChangeListener listener )
248 		{
249 		}
250 
251 		public ModelItem getModelItem()
252 		{
253 			return groovyStep;
254 		}
255 	}
256 
257 	private class RunAction extends AbstractAction
258 	{
259 		public RunAction()
260 		{
261 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ) );
262 			putValue( Action.SHORT_DESCRIPTION,
263 					"Runs this script in a seperate thread using a mock testRunner and testContext" );
264 		}
265 
266 		public void actionPerformed( ActionEvent e )
267 		{
268 			SoapUI.getThreadPool().execute( new Runnable()
269 			{
270 				public void run()
271 				{
272 					MockTestRunner mockTestRunner = new MockTestRunner( groovyStep.getTestCase(), logger );
273 					statusBar.setIndeterminate( true );
274 					WsdlTestStepResult result = ( WsdlTestStepResult )groovyStep.run( mockTestRunner,
275 							new MockTestRunContext( mockTestRunner, groovyStep ) );
276 					statusBar.setIndeterminate( false );
277 
278 					Throwable er = result.getError();
279 					if( er != null )
280 					{
281 						String message = er.getMessage();
282 
283 						// ugly...
284 						editor.selectError( message );
285 
286 						UISupport.showErrorMessage( er.toString() );
287 						editor.requestFocus();
288 					}
289 					else if( result.getMessages().length > 0 )
290 					{
291 						UISupport.showInfoMessage( StringUtils.join( result.getMessages(), "\n" ) );
292 					}
293 				}
294 			} );
295 		}
296 	}
297 
298 	public void propertyChange( PropertyChangeEvent evt )
299 	{
300 		if( evt.getPropertyName().equals( "script" ) && !updating )
301 		{
302 			updating = true;
303 			editor.getEditArea().setText( ( String )evt.getNewValue() );
304 			updating = false;
305 		}
306 	}
307 }