View Javadoc

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