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