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