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.teststeps.assertions.basic;
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.MouseAdapter;
20  import java.awt.event.MouseEvent;
21  
22  import javax.swing.AbstractAction;
23  import javax.swing.Action;
24  import javax.swing.BorderFactory;
25  import javax.swing.Box;
26  import javax.swing.JButton;
27  import javax.swing.JComponent;
28  import javax.swing.JDialog;
29  import javax.swing.JLabel;
30  import javax.swing.JPanel;
31  import javax.swing.JSplitPane;
32  
33  import org.apache.log4j.Logger;
34  import org.apache.xmlbeans.XmlObject;
35  
36  import com.eviware.soapui.SoapUI;
37  import com.eviware.soapui.config.TestAssertionConfig;
38  import com.eviware.soapui.impl.rest.RestRequestInterface;
39  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
40  import com.eviware.soapui.impl.wsdl.panels.mockoperation.WsdlMockResponseMessageExchange;
41  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
42  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
43  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
44  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
45  import com.eviware.soapui.impl.wsdl.teststeps.HttpResponseMessageExchange;
46  import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequestStepInterface;
47  import com.eviware.soapui.impl.wsdl.teststeps.RestResponseMessageExchange;
48  import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStepInterface;
49  import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
50  import com.eviware.soapui.impl.wsdl.teststeps.WsdlMockResponseTestStep;
51  import com.eviware.soapui.impl.wsdl.teststeps.WsdlResponseMessageExchange;
52  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
53  import com.eviware.soapui.impl.wsdl.teststeps.assertions.AbstractTestAssertionFactory;
54  import com.eviware.soapui.model.iface.MessageExchange;
55  import com.eviware.soapui.model.iface.SubmitContext;
56  import com.eviware.soapui.model.testsuite.Assertable;
57  import com.eviware.soapui.model.testsuite.AssertionError;
58  import com.eviware.soapui.model.testsuite.AssertionException;
59  import com.eviware.soapui.model.testsuite.RequestAssertion;
60  import com.eviware.soapui.model.testsuite.ResponseAssertion;
61  import com.eviware.soapui.model.testsuite.TestStep;
62  import com.eviware.soapui.support.UISupport;
63  import com.eviware.soapui.support.components.JXToolBar;
64  import com.eviware.soapui.support.log.JLogList;
65  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
66  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
67  import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
68  import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
69  import com.jgoodies.forms.builder.ButtonBarBuilder;
70  
71  /***
72   * Assertion performed by a custom Grooy Script
73   * 
74   * @author ole.matzura
75   */
76  
77  public class GroovyScriptAssertion extends WsdlMessageAssertion implements RequestAssertion, ResponseAssertion
78  {
79  	public static final String ID = "GroovyScriptAssertion";
80  	public static final String LABEL = "Script Assertion";
81  	private String scriptText;
82  	private SoapUIScriptEngine scriptEngine;
83  	private JDialog dialog;
84  	private GroovyScriptAssertionPanel groovyScriptAssertionPanel;
85  	private String oldScriptText;
86  
87  	public GroovyScriptAssertion( TestAssertionConfig assertionConfig, Assertable modelItem )
88  	{
89  		super( assertionConfig, modelItem, true, true, true, false );
90  
91  		XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( getConfiguration() );
92  		scriptText = reader.readString( "scriptText", "" );
93  
94  		scriptEngine = SoapUIScriptEngineRegistry.create( this );
95  		scriptEngine.setScript( scriptText );
96  	}
97  
98  	@Override
99  	protected String internalAssertRequest( MessageExchange messageExchange, SubmitContext context )
100 			throws AssertionException
101 	{
102 		return assertScript( messageExchange, context, SoapUI.ensureGroovyLog() );
103 	}
104 
105 	private String assertScript( MessageExchange messageExchange, SubmitContext context, Logger log )
106 			throws AssertionException
107 	{
108 		try
109 		{
110 			scriptEngine.setVariable( "context", context );
111 			scriptEngine.setVariable( "messageExchange", messageExchange );
112 			scriptEngine.setVariable( "log", log );
113 
114 			Object result = scriptEngine.run();
115 			return result == null ? null : result.toString();
116 		}
117 		catch( Throwable e )
118 		{
119 			throw new AssertionException( new AssertionError( e.getMessage() ) );
120 		}
121 		finally
122 		{
123 			scriptEngine.clearVariables();
124 		}
125 	}
126 
127 	@Override
128 	protected String internalAssertResponse( MessageExchange messageExchange, SubmitContext context )
129 			throws AssertionException
130 	{
131 		return assertScript( messageExchange, context, SoapUI.ensureGroovyLog() );
132 	}
133 
134 	@Override
135 	public boolean configure()
136 	{
137 		if( dialog == null )
138 		{
139 			buildDialog();
140 		}
141 
142 		oldScriptText = scriptText;
143 		UISupport.showDialog( dialog );
144 		return true;
145 	}
146 
147 	protected void buildDialog()
148 	{
149 		dialog = new JDialog( UISupport.getMainFrame(), "Script Assertion", true );
150 		groovyScriptAssertionPanel = new GroovyScriptAssertionPanel();
151 		dialog.setContentPane( groovyScriptAssertionPanel );
152 		UISupport.initDialogActions( dialog, groovyScriptAssertionPanel.getShowOnlineHelpAction(),
153 				groovyScriptAssertionPanel.getDefaultButton() );
154 		dialog.setSize( 600, 500 );
155 		dialog.setModal( true );
156 		dialog.pack();
157 	}
158 
159 	protected GroovyScriptAssertionPanel getScriptAssertionPanel()
160 	{
161 		return groovyScriptAssertionPanel;
162 	}
163 
164 	protected XmlObject createConfiguration()
165 	{
166 		XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
167 		builder.add( "scriptText", scriptText );
168 		return builder.finish();
169 	}
170 
171 	public String getScriptText()
172 	{
173 		return scriptText;
174 	}
175 
176 	public void setScriptText( String scriptText )
177 	{
178 		this.scriptText = scriptText;
179 		scriptEngine.setScript( scriptText );
180 		setConfiguration( createConfiguration() );
181 	}
182 
183 	protected class GroovyScriptAssertionPanel extends JPanel
184 	{
185 		private GroovyEditor editor;
186 		private JSplitPane mainSplit;
187 		private JLogList logArea;
188 		private RunAction runAction = new RunAction();
189 		private Logger logger;
190 		private JButton okButton;
191 		private ShowOnlineHelpAction showOnlineHelpAction;
192 		public String oldscriptText;
193 
194 		public GroovyScriptAssertionPanel()
195 		{
196 			super( new BorderLayout() );
197 
198 			buildUI();
199 			setPreferredSize( new Dimension( 600, 440 ) );
200 
201 			logger = Logger.getLogger( "ScriptAssertion." + getName() );
202 			editor.requestFocusInWindow();
203 		}
204 
205 		public GroovyEditor getGroovyEditor()
206 		{
207 			return editor;
208 		}
209 
210 		public void release()
211 		{
212 			logArea.release();
213 			editor.release();
214 			logger = null;
215 		}
216 
217 		private void buildUI()
218 		{
219 			editor = new GroovyEditor( new ScriptStepGroovyEditorModel() );
220 
221 			logArea = new JLogList( "Groovy Test Log" );
222 			logArea.addLogger( "ScriptAssertion." + getName(), true );
223 			logArea.getLogList().addMouseListener( new MouseAdapter()
224 			{
225 
226 				public void mouseClicked( MouseEvent e )
227 				{
228 					if( e.getClickCount() < 2 )
229 						return;
230 
231 					String value = logArea.getLogList().getSelectedValue().toString();
232 					if( value == null )
233 						return;
234 
235 					editor.selectError( value );
236 				}
237 			} );
238 
239 			editor.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 0, 3, 0, 3 ), editor
240 					.getBorder() ) );
241 
242 			mainSplit = UISupport.createVerticalSplit( editor, logArea );
243 			mainSplit.setDividerLocation( 280 );
244 			mainSplit.setResizeWeight( 0.8 );
245 			add( mainSplit, BorderLayout.CENTER );
246 			add( buildToolbar(), BorderLayout.NORTH );
247 			add( buildStatusBar(), BorderLayout.SOUTH );
248 		}
249 
250 		public JButton getDefaultButton()
251 		{
252 			return okButton;
253 		}
254 
255 		public ShowOnlineHelpAction getShowOnlineHelpAction()
256 		{
257 			return showOnlineHelpAction;
258 		}
259 
260 		private Component buildStatusBar()
261 		{
262 			ButtonBarBuilder builder = new ButtonBarBuilder();
263 
264 			showOnlineHelpAction = new ShowOnlineHelpAction( HelpUrls.GROOVYASSERTION_HELP_URL );
265 			builder.addFixed( UISupport.createToolbarButton( showOnlineHelpAction ) );
266 			builder.addGlue();
267 			okButton = new JButton( new OkAction() );
268 			builder.addFixed( okButton );
269 			builder.addRelatedGap();
270 			builder.addFixed( new JButton( new CancelAction() ) );
271 			builder.setBorder( BorderFactory.createEmptyBorder( 0, 3, 3, 3 ) );
272 			return builder.getPanel();
273 		}
274 
275 		private JComponent buildToolbar()
276 		{
277 			JXToolBar toolBar = UISupport.createToolbar();
278 			JButton runButton = UISupport.createToolbarButton( runAction );
279 			toolBar.add( runButton );
280 			toolBar.add( Box.createHorizontalGlue() );
281 			JLabel label = new JLabel( "<html>Script is invoked with <code>log</code>, <code>context</code> "
282 					+ "and <code>messageExchange</code> variables</html>" );
283 			label.setToolTipText( label.getText() );
284 			label.setMaximumSize( label.getPreferredSize() );
285 
286 			toolBar.addFixed( label );
287 			toolBar.addSpace( 3 );
288 
289 			return toolBar;
290 		}
291 
292 		private final class OkAction extends AbstractAction
293 		{
294 			public OkAction()
295 			{
296 				super( "OK" );
297 			}
298 
299 			public void actionPerformed( ActionEvent e )
300 			{
301 				dialog.setVisible( false );
302 				setScriptText( editor.getEditArea().getText() );
303 			}
304 		}
305 
306 		private final class CancelAction extends AbstractAction
307 		{
308 			public CancelAction()
309 			{
310 				super( "Cancel" );
311 			}
312 
313 			public void actionPerformed( ActionEvent e )
314 			{
315 				dialog.setVisible( false );
316 				editor.getEditArea().setText( oldScriptText );
317 			}
318 		}
319 
320 		private class ScriptStepGroovyEditorModel extends AbstractGroovyEditorModel
321 		{
322 			public ScriptStepGroovyEditorModel()
323 			{
324 				super( new String[] { "log", "context", "messageExchange" }, getAssertable().getModelItem(), "Assertion" );
325 			}
326 
327 			public Action getRunAction()
328 			{
329 				return runAction;
330 			}
331 
332 			public String getScript()
333 			{
334 				return getScriptText();
335 			}
336 
337 			public void setScript( String text )
338 			{
339 
340 			}
341 		}
342 
343 		private class RunAction extends AbstractAction
344 		{
345 			public RunAction()
346 			{
347 				putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ) );
348 				putValue( Action.SHORT_DESCRIPTION,
349 						"Runs this assertion script against the last messageExchange with a mock testContext" );
350 			}
351 
352 			public void actionPerformed( ActionEvent e )
353 			{
354 				TestStep testStep = ( TestStep )getAssertable().getModelItem();
355 				MessageExchange exchange = null;
356 
357 				if( testStep instanceof WsdlTestRequestStep )
358 				{
359 					WsdlTestRequestStep testRequestStep = ( WsdlTestRequestStep )testStep;
360 					exchange = new WsdlResponseMessageExchange( testRequestStep.getTestRequest() );
361 					( ( WsdlResponseMessageExchange )exchange ).setResponse( testRequestStep.getTestRequest().getResponse() );
362 				}
363 				else if( testStep instanceof RestTestRequestStepInterface )
364 				{
365 					RestTestRequestStepInterface testRequestStep = ( RestTestRequestStepInterface )testStep;
366 					exchange = new RestResponseMessageExchange( ( RestRequestInterface )testRequestStep.getTestRequest() );
367 					( ( RestResponseMessageExchange )exchange ).setResponse( testRequestStep.getTestRequest().getResponse() );
368 				}
369 				else if( testStep instanceof HttpTestRequestStepInterface )
370 				{
371 					HttpTestRequestStepInterface testRequestStep = ( HttpTestRequestStepInterface )testStep;
372 					exchange = new HttpResponseMessageExchange( testRequestStep.getTestRequest() );
373 					( ( HttpResponseMessageExchange )exchange ).setResponse( testRequestStep.getTestRequest().getResponse() );
374 				}
375 				else if( testStep instanceof WsdlMockResponseTestStep )
376 				{
377 					WsdlMockResponseTestStep mockResponseStep = ( WsdlMockResponseTestStep )testStep;
378 					exchange = new WsdlMockResponseMessageExchange( mockResponseStep.getMockResponse() );
379 				}
380 
381 				try
382 				{
383 					setScriptText( editor.getEditArea().getText() );
384 					String result = assertScript( exchange, new WsdlTestRunContext( testStep ), logger );
385 					UISupport
386 							.showInfoMessage( "Script Assertion Passed" + ( ( result == null ) ? "" : ": [" + result + "]" ) );
387 				}
388 				catch( AssertionException e1 )
389 				{
390 					UISupport.showErrorMessage( e1.getMessage() );
391 				}
392 				catch( Throwable t )
393 				{
394 					SoapUI.logError( t );
395 					UISupport.showErrorMessage( t.getMessage() );
396 				}
397 
398 				editor.requestFocusInWindow();
399 			}
400 		}
401 	}
402 
403 	@Override
404 	public void release()
405 	{
406 		super.release();
407 		scriptEngine.release();
408 
409 		if( groovyScriptAssertionPanel != null )
410 			groovyScriptAssertionPanel.release();
411 	}
412 
413 	public static class Factory extends AbstractTestAssertionFactory
414 	{
415 		public Factory()
416 		{
417 			super( GroovyScriptAssertion.ID, GroovyScriptAssertion.LABEL, GroovyScriptAssertion.class );
418 		}
419 	}
420 }