View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.panels.teststeps;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.event.ActionEvent;
18  import java.beans.PropertyChangeEvent;
19  import java.util.Date;
20  
21  import javax.swing.AbstractAction;
22  import javax.swing.Action;
23  import javax.swing.JButton;
24  import javax.swing.JComponent;
25  import javax.swing.JLabel;
26  import javax.swing.JPanel;
27  import javax.swing.JScrollPane;
28  import javax.swing.JSplitPane;
29  import javax.swing.JTextArea;
30  import javax.swing.JTextField;
31  import javax.swing.text.Document;
32  
33  import com.eviware.soapui.SoapUI;
34  import com.eviware.soapui.impl.support.components.ModelItemXmlEditor;
35  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
36  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResult;
37  import com.eviware.soapui.impl.wsdl.panels.mockoperation.AbstractWsdlMockResponseDesktopPanel;
38  import com.eviware.soapui.impl.wsdl.teststeps.WsdlMockResponseTestStep;
39  import com.eviware.soapui.model.ModelItem;
40  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
41  import com.eviware.soapui.model.support.TestRunListenerAdapter;
42  import com.eviware.soapui.model.testsuite.Assertable;
43  import com.eviware.soapui.model.testsuite.AssertionError;
44  import com.eviware.soapui.model.testsuite.LoadTestRunner;
45  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
46  import com.eviware.soapui.model.testsuite.TestCaseRunner;
47  import com.eviware.soapui.model.testsuite.TestStep;
48  import com.eviware.soapui.model.testsuite.TestStepResult;
49  import com.eviware.soapui.monitor.support.TestMonitorListenerAdapter;
50  import com.eviware.soapui.support.DocumentListenerAdapter;
51  import com.eviware.soapui.support.ModelItemPropertyEditorModel;
52  import com.eviware.soapui.support.StringUtils;
53  import com.eviware.soapui.support.UISupport;
54  import com.eviware.soapui.support.components.JComponentInspector;
55  import com.eviware.soapui.support.components.JInspectorPanel;
56  import com.eviware.soapui.support.components.JInspectorPanelFactory;
57  import com.eviware.soapui.support.components.JXToolBar;
58  import com.eviware.soapui.support.xml.XmlUtils;
59  
60  public class WsdlMockResponseStepDesktopPanel extends
61  		AbstractWsdlMockResponseDesktopPanel<WsdlMockResponseTestStep, WsdlMockResponse>
62  {
63  	private JTextArea logArea;
64  	private AssertionsPanel assertionsPanel;
65  	private JTextField portField;
66  	private JTextField pathField;
67  	private InternalTestRunListener testRunListener;
68  	private InternalTestMonitorListener testMonitorListener = new InternalTestMonitorListener();
69  	private JInspectorPanel inspectorPanel;
70  	private JComponentInspector<JComponent> assertionInspector;
71  	private JComponentInspector<JComponent> logInspector;
72  	private ModelItemPropertyEditorModel<WsdlMockResponseTestStep> queryEditorModel;
73  	private ModelItemPropertyEditorModel<WsdlMockResponseTestStep> matchEditorModel;
74  
75  	public WsdlMockResponseStepDesktopPanel( WsdlMockResponseTestStep mockResponseStep )
76  	{
77  		super( mockResponseStep );
78  		init( mockResponseStep.getMockResponse() );
79  
80  		testRunListener = new InternalTestRunListener();
81  		mockResponseStep.getTestCase().addTestRunListener( testRunListener );
82  
83  		SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
84  		setEnabled( !SoapUI.getTestMonitor().hasRunningTest( mockResponseStep.getTestCase() ) );
85  	}
86  
87  	@Override
88  	protected JComponent buildContent()
89  	{
90  		inspectorPanel = JInspectorPanelFactory.build( super.buildContent() );
91  
92  		assertionsPanel = buildAssertionsPanel();
93  
94  		assertionInspector = new JComponentInspector<JComponent>( assertionsPanel, "Assertions ("
95  				+ getModelItem().getAssertionCount() + ")", "Assertions for this Test Request", true );
96  
97  		inspectorPanel.addInspector( assertionInspector );
98  
99  		logInspector = new JComponentInspector<JComponent>( buildLogPanel(), "Request Log (0)", "Log of requests", true );
100 		inspectorPanel.addInspector( logInspector );
101 
102 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildQueryMatchPanel(), "Query/Match",
103 				"Query/Match configuration", true ) );
104 
105 		inspectorPanel.setDefaultDividerLocation( 0.6F );
106 		inspectorPanel.setCurrentInspector( "Assertions" );
107 
108 		updateStatusIcon();
109 
110 		return inspectorPanel.getComponent();
111 	}
112 
113 	private void updateStatusIcon()
114 	{
115 		Assertable.AssertionStatus status = getModelItem().getAssertionStatus();
116 		switch( status )
117 		{
118 		case FAILED :
119 		{
120 			assertionInspector.setIcon( UISupport.createImageIcon( "/failed_assertion.gif" ) );
121 			inspectorPanel.activate( assertionInspector );
122 			break;
123 		}
124 		case UNKNOWN :
125 		{
126 			assertionInspector.setIcon( UISupport.createImageIcon( "/unknown_assertion.gif" ) );
127 			break;
128 		}
129 		case VALID :
130 		{
131 			assertionInspector.setIcon( UISupport.createImageIcon( "/valid_assertion.gif" ) );
132 			inspectorPanel.deactivate();
133 			break;
134 		}
135 		}
136 	}
137 
138 	private JComponent buildLogPanel()
139 	{
140 		logArea = new JTextArea();
141 		logArea.setEditable( false );
142 		logArea.setToolTipText( "Response Log" );
143 
144 		JPanel panel = new JPanel( new BorderLayout() );
145 		panel.add( new JScrollPane( logArea ), BorderLayout.CENTER );
146 
147 		return panel;
148 	}
149 
150 	public void setContent( JComponent content )
151 	{
152 		inspectorPanel.setContentComponent( content );
153 	}
154 
155 	public void removeContent( JComponent content )
156 	{
157 		inspectorPanel.setContentComponent( null );
158 	}
159 
160 	@Override
161 	protected void createToolbar( JXToolBar toolbar )
162 	{
163 		toolbar.addUnrelatedGap();
164 		toolbar.addFixed( new JLabel( "Path" ) );
165 		toolbar.addRelatedGap();
166 		pathField = new JTextField( getModelItem().getPath(), 15 );
167 		pathField.getDocument().addDocumentListener( new DocumentListenerAdapter()
168 		{
169 
170 			@Override
171 			public void update( Document document )
172 			{
173 				getModelItem().setPath( pathField.getText() );
174 			}
175 		} );
176 
177 		toolbar.addFixed( pathField );
178 
179 		toolbar.addUnrelatedGap();
180 		toolbar.addFixed( new JLabel( "Port" ) );
181 		toolbar.addRelatedGap();
182 		portField = new JTextField( String.valueOf( getModelItem().getPort() ), 5 );
183 		portField.getDocument().addDocumentListener( new DocumentListenerAdapter()
184 		{
185 
186 			@Override
187 			public void update( Document document )
188 			{
189 				try
190 				{
191 					getModelItem().setPort( Integer.parseInt( portField.getText() ) );
192 				}
193 				catch( NumberFormatException e )
194 				{
195 				}
196 			}
197 		} );
198 
199 		toolbar.addFixed( portField );
200 	}
201 
202 	private JComponent buildQueryMatchPanel()
203 	{
204 		JPanel panel = new JPanel( new BorderLayout() );
205 		panel.add( buildQueryMatchToolbar(), BorderLayout.NORTH );
206 		JSplitPane splitPane = UISupport.createHorizontalSplit( buildQueryEditor(), buildMatchEditor() );
207 		panel.add( splitPane, BorderLayout.CENTER );
208 		splitPane.setDividerLocation( 200 );
209 		return panel;
210 	}
211 	
212 	private Component buildMatchEditor()
213 	{
214 		JPanel panel = new JPanel( new BorderLayout() );
215 
216 		matchEditorModel = new ModelItemPropertyEditorModel<WsdlMockResponseTestStep>( getModelItem(), "match" );
217 		panel.add( UISupport.getEditorFactory().buildXmlEditor( matchEditorModel ), BorderLayout.CENTER );
218 
219 		UISupport.addTitledBorder( panel, "Matching Value" );
220 
221 		return panel;
222 	}
223 
224 	private Component buildQueryEditor()
225 	{
226 		JPanel panel = new JPanel( new BorderLayout() );
227 
228 		queryEditorModel = new ModelItemPropertyEditorModel<WsdlMockResponseTestStep>( getModelItem(), "query" );
229 		panel.add( UISupport.getEditorFactory().buildXPathEditor( queryEditorModel ), BorderLayout.CENTER );
230 
231 		UISupport.addTitledBorder( panel, "XPath Query" );
232 
233 		return panel;
234 	}
235 
236 	protected JXToolBar buildQueryMatchToolbar()
237 	{
238 		JXToolBar toolBar = UISupport.createSmallToolbar();
239 		toolBar.addFixed( new JButton( new SelectFromCurrentAction() ) );
240 		return toolBar;
241 	}
242 	
243 	public class SelectFromCurrentAction extends AbstractAction
244 	{
245 		public SelectFromCurrentAction()
246 		{
247 			super( "Select from current" );
248 			putValue( Action.SHORT_DESCRIPTION,
249 					"Selects the Query XPath expression from the last request Match field" );
250 		}
251 
252 		public void actionPerformed( ActionEvent arg0 )
253 		{
254 			if( getModelItem().getLastResult() != null && 
255 					getModelItem().getLastResult().getMockRequest() != null && StringUtils.hasContent(  getModelItem().getQuery() ) )
256 			{
257 				getModelItem().setMatch( XmlUtils.getXPathValue( getModelItem().getLastResult().getMockRequest().getRequestContent(), 
258 						PropertyExpander.expandProperties( getModelItem(), getModelItem().getQuery() )));
259 			}
260 		}
261 	}
262 
263 	private AssertionsPanel buildAssertionsPanel()
264 	{
265 		assertionsPanel = new AssertionsPanel( getModelItem() )
266 		{
267 			protected void selectError( AssertionError error )
268 			{
269 				ModelItemXmlEditor<?, ?> editor = getResponseEditor();
270 				editor.requestFocus();
271 			}
272 		};
273 
274 		return assertionsPanel;
275 	}
276 
277 	@Override
278 	public boolean onClose( boolean canCancel )
279 	{
280 		getModelItem().getTestCase().removeTestRunListener( testRunListener );
281 		SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
282 		assertionsPanel.release();
283 
284 		queryEditorModel.release();
285 		matchEditorModel.release();
286 
287 		inspectorPanel.release();
288 
289 		return super.onClose( canCancel );
290 	}
291 
292 	public void setEnabled( boolean enabled )
293 	{
294 		super.setEnabled( enabled );
295 
296 		pathField.setEnabled( enabled );
297 		portField.setEnabled( enabled );
298 	}
299 
300 	public boolean dependsOn( ModelItem modelItem )
301 	{
302 		return modelItem == getModelItem() || modelItem == getModelItem().getTestCase()
303 				|| modelItem == getModelItem().getOperation() || modelItem == getModelItem().getOperation().getInterface()
304 				|| modelItem == getModelItem().getTestCase().getTestSuite()
305 				|| modelItem == getModelItem().getTestCase().getTestSuite().getProject();
306 	}
307 
308 	public class InternalTestRunListener extends TestRunListenerAdapter
309 	{
310 		@Override
311 		public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
312 		{
313 			setEnabled( true );
314 		}
315 
316 		@Override
317 		public void beforeRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
318 		{
319 			setEnabled( false );
320 		}
321 
322 		@Override
323 		public void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep )
324 		{
325 			if( testStep == getModelItem() )
326 			{
327 				logArea.setText( logArea.getText() + new Date( System.currentTimeMillis() ).toString()
328 						+ ": Waiting for request on http://127.0.0.1:" + getModelItem().getPort() + getModelItem().getPath()
329 						+ "\r\n" );
330 			}
331 		}
332 
333 		@Override
334 		public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result )
335 		{
336 			if( result.getTestStep() == getModelItem() )
337 			{
338 				String msg = new Date( result.getTimeStamp() ).toString() + ": Handled request in " + result.getTimeTaken()
339 						+ "ms";
340 				logArea.setText( logArea.getText() + msg + "\r\n" );
341 			}
342 		}
343 	}
344 
345 	private class InternalTestMonitorListener extends TestMonitorListenerAdapter
346 	{
347 		public void loadTestFinished( LoadTestRunner runner )
348 		{
349 			setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
350 		}
351 
352 		public void loadTestStarted( LoadTestRunner runner )
353 		{
354 			if( runner.getLoadTest().getTestCase() == getModelItem().getTestCase() )
355 				setEnabled( false );
356 		}
357 
358 		public void testCaseFinished( TestCaseRunner runner )
359 		{
360 			setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
361 		}
362 
363 		public void testCaseStarted( TestCaseRunner runner )
364 		{
365 			if( runner.getTestCase() == getModelItem().getTestCase() )
366 				setEnabled( false );
367 		}
368 	}
369 
370 	public void propertyChange( PropertyChangeEvent evt )
371 	{
372 		super.propertyChange( evt );
373 
374 		if( evt.getPropertyName().equals( WsdlMockResponseTestStep.STATUS_PROPERTY ) )
375 			updateStatusIcon();
376 	}
377 
378 	@SuppressWarnings("unused")
379 	private final class DeclareNamespacesAction extends AbstractAction
380 	{
381 		public DeclareNamespacesAction()
382 		{
383 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/declareNs.gif" ) );
384 			putValue( Action.SHORT_DESCRIPTION,
385 					"Declare available response/request namespaces in source/target expressions" );
386 		}
387 
388 		public void actionPerformed( ActionEvent e )
389 		{
390 			try
391 			{
392 				WsdlMockResult lastResult = getMockResponse().getMockResult();
393 				String content = null;
394 				if( lastResult == null )
395 				{
396 					if( !UISupport.confirm( "Missing last result, declare from default request instead?",
397 							"Declare Namespaces" ) )
398 					{
399 						return;
400 					}
401 
402 					content = getMockResponse().getMockOperation().getOperation().createRequest( true );
403 				}
404 				else
405 				{
406 					content = lastResult.getMockRequest().getRequestContent();
407 				}
408 
409 				String path = getModelItem().getQuery();
410 				if( path == null )
411 					path = "";
412 
413 				getModelItem().setQuery( XmlUtils.declareXPathNamespaces( content ) + path );
414 			}
415 			catch( Exception e1 )
416 			{
417 				UISupport.showErrorMessage( e1 );
418 			}
419 		}
420 	}
421 
422 }