View Javadoc

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