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