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 );
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 			dialog.pack();
129 		}
130 
131 		dialog.setVisible( true );
132 		
133 		setConfiguration( createConfiguration() );
134 		return true;
135 	}
136 
137 	protected XmlObject createConfiguration()
138 	{
139 		XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
140 		builder.add( "scriptText", scriptText );
141 		return builder.finish();
142 	}
143 
144 	private class GroovyScriptAssertionPanel extends JPanel
145 	{
146 		private GroovyEditor editor;
147 		private JSplitPane mainSplit;
148 		private JLogList logArea;
149 		private RunAction runAction = new RunAction();
150 		private Logger logger;
151 
152 		public GroovyScriptAssertionPanel()
153 		{
154 			super( new BorderLayout() );
155 			
156 			buildUI();
157 			setPreferredSize( new Dimension( 600, 440 ));
158 			
159 			logger = Logger.getLogger( "ScriptAssertion." + getName() );
160 			editor.requestFocusInWindow();
161 		}
162 
163 		public void release()
164 		{
165 			logArea.release();
166 			logger = null;
167 		}
168 		
169 		private void buildUI()
170 		{
171 			editor = new GroovyEditor( new ScriptStepGroovyEditorModel( ));
172 			
173 			logArea = new JLogList( "Groovy Test Log" );
174 			logArea.addLogger( "ScriptAssertion." + getName(), true );
175 			logArea.getLogList().addMouseListener( new MouseAdapter() {
176 
177 				public void mouseClicked(MouseEvent e)
178 				{
179 					if( e.getClickCount() < 2 )
180 						return;
181 					
182 					String value = logArea.getLogList().getSelectedValue().toString();
183 					if( value == null )
184 						return;
185 					
186 					editor.selectError( value );
187 				}} );
188 			
189 			JScrollPane scrollPane = new JScrollPane( editor );
190 			scrollPane.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 0, 3, 0, 3 ), 
191 						scrollPane.getBorder() ));
192 			
193 			mainSplit = UISupport.createVerticalSplit( scrollPane, logArea);
194 			mainSplit.setDividerLocation( 280 );
195 			mainSplit.setResizeWeight( 0.8 );
196 			add( mainSplit, BorderLayout.CENTER );
197 			add( buildToolbar(), BorderLayout.NORTH );
198 			add( buildStatusBar(), BorderLayout.SOUTH );
199 		}
200 		
201 		private Component buildStatusBar()
202 		{
203 			ButtonBarBuilder builder = new ButtonBarBuilder();
204 			
205 			builder.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.GROOVYASSERTION_HELP_URL )));
206 			builder.addGlue();
207 			builder.addFixed( new JButton( new OkAction() ) );
208 			builder.setBorder( BorderFactory.createEmptyBorder( 0, 3, 3, 3 ));
209 			return builder.getPanel();
210 		}
211 
212 		private JComponent buildToolbar()
213 		{
214 			JXToolBar toolBar = UISupport.createToolbar();
215 			JButton runButton = UISupport.createToolbarButton( runAction );
216 			toolBar.add( runButton );
217 			toolBar.add( Box.createHorizontalGlue() );
218 			JLabel label = new JLabel("<html>Script is invoked with <code>log</code>, <code>context</code> " +
219 							"and <code>messageExchange</code> variables</html>");
220 			label.setToolTipText( label.getText() );
221 			label.setMaximumSize( label.getPreferredSize() );
222 			
223 			toolBar.addFixed( label);
224 			toolBar.addSpace( 3 );
225 			
226 			return toolBar;
227 		}
228 
229 		private final class OkAction extends AbstractAction
230 		{
231 			public OkAction()
232 			{
233 			   super( "OK" );	
234 			}
235 			
236 			public void actionPerformed( ActionEvent e )
237 			{
238 				dialog.setVisible( false );
239 			}
240 		}
241 
242 		private class ScriptStepGroovyEditorModel implements GroovyEditorModel
243 		{
244 			public String[] getKeywords()
245 			{
246 				return new String[] {"log", "context", "messageExchange"};
247 			}
248 
249 			public Action getRunAction()
250 			{
251 				return runAction;
252 			}
253 
254 			public String getScript()
255 			{
256 				return scriptText;
257 			}
258 
259 			public void setScript( String text )
260 			{
261 				scriptText = text;
262 				scriptEngine.setScript( scriptText );
263 			}
264 
265 			public Settings getSettings()
266 			{
267 				return SoapUI.getSettings();
268 			}}
269 		
270 		private class RunAction extends AbstractAction
271 		{
272 			public RunAction()
273 			{
274 				putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ));
275 				putValue( Action.SHORT_DESCRIPTION, "Runs this assertion script against the last messageExchange with a mock testContext" );
276 			}
277 
278 			public void actionPerformed(ActionEvent e)
279 			{
280 				TestStep testStep = getAssertable().getTestStep();
281 				WsdlMessageExchange exchange = null;
282 				
283 				if( testStep instanceof WsdlTestRequestStep )
284 				{
285 					WsdlTestRequestStep testRequestStep = ( WsdlTestRequestStep ) testStep;
286 					exchange = new WsdlResponseMessageExchange( testRequestStep.getTestRequest() );
287 					((WsdlResponseMessageExchange)exchange).setResponse( testRequestStep.getTestRequest().getResponse() );
288 				}
289 				
290 				try
291 				{
292 					String result = assertScript( exchange, new WsdlTestRunContext( testStep ), logger );
293 					UISupport.showInfoMessage( "Script Assertion Passed" + ((result==null) ? "" : ": [" + result + "]" ));
294 				}
295 				catch( AssertionException e1 )
296 				{
297 					UISupport.showErrorMessage( e1.getMessage() );
298 				}
299 				catch( Throwable t )
300 				{
301 					SoapUI.logError( t );
302 					UISupport.showErrorMessage( t.getMessage() );
303 				}
304 				
305 				editor.requestFocusInWindow();
306 			}
307 		}
308 	}
309 
310 	@Override
311 	public void release()
312 	{
313 		super.release();
314 		
315 		scriptEngine.release();
316 		
317 		if( groovyScriptAssertionPanel != null )
318 			groovyScriptAssertionPanel.release();
319 	}
320 }