View Javadoc

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