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 }