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