View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com
3    */
4   
5   package com.eviware.soapui.impl.wsdl.panels.teststeps;
6   
7   import java.awt.BorderLayout;
8   import java.awt.Dimension;
9   import java.awt.dnd.DnDConstants;
10  import java.awt.dnd.DropTarget;
11  import java.awt.event.ActionEvent;
12  import java.awt.event.FocusAdapter;
13  import java.awt.event.FocusEvent;
14  import java.awt.event.ItemEvent;
15  import java.awt.event.ItemListener;
16  import java.beans.PropertyChangeEvent;
17  import java.beans.PropertyChangeListener;
18  import java.sql.Connection;
19  import java.text.SimpleDateFormat;
20  import java.util.ArrayList;
21  import java.util.Date;
22  import java.util.List;
23  
24  import javax.swing.AbstractAction;
25  import javax.swing.Action;
26  import javax.swing.BorderFactory;
27  import javax.swing.Box;
28  import javax.swing.DefaultCellEditor;
29  import javax.swing.JButton;
30  import javax.swing.JCheckBox;
31  import javax.swing.JComponent;
32  import javax.swing.JPanel;
33  import javax.swing.JPasswordField;
34  import javax.swing.JScrollPane;
35  import javax.swing.JSplitPane;
36  import javax.swing.JTabbedPane;
37  import javax.swing.JTable;
38  import javax.swing.JTextField;
39  import javax.swing.JToggleButton;
40  import javax.swing.ListModel;
41  import javax.swing.SwingUtilities;
42  import javax.swing.TransferHandler;
43  import javax.swing.event.ChangeEvent;
44  import javax.swing.event.ChangeListener;
45  import javax.swing.event.ListSelectionEvent;
46  import javax.swing.event.ListSelectionListener;
47  import javax.swing.text.Document;
48  
49  import org.apache.log4j.Logger;
50  
51  import com.eviware.soapui.SoapUI;
52  import com.eviware.soapui.config.JdbcRequestTestStepConfig;
53  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
54  import com.eviware.soapui.impl.support.components.ModelItemXmlEditor;
55  import com.eviware.soapui.impl.support.components.ResponseMessageXmlEditor;
56  import com.eviware.soapui.impl.support.panels.AbstractHttpRequestDesktopPanel;
57  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
58  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.DefaultPropertyTableHolderModel;
59  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
60  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
61  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
62  import com.eviware.soapui.impl.wsdl.teststeps.JdbcRequestTestStep;
63  import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
64  import com.eviware.soapui.model.ModelItem;
65  import com.eviware.soapui.model.iface.Submit;
66  import com.eviware.soapui.model.iface.SubmitContext;
67  import com.eviware.soapui.model.iface.SubmitListener;
68  import com.eviware.soapui.model.iface.Request.SubmitException;
69  import com.eviware.soapui.model.iface.Submit.Status;
70  import com.eviware.soapui.model.testsuite.Assertable;
71  import com.eviware.soapui.model.testsuite.AssertionsListener;
72  import com.eviware.soapui.model.testsuite.LoadTestRunner;
73  import com.eviware.soapui.model.testsuite.TestAssertion;
74  import com.eviware.soapui.model.testsuite.TestCaseRunner;
75  import com.eviware.soapui.model.testsuite.Assertable.AssertionStatus;
76  import com.eviware.soapui.monitor.support.TestMonitorListenerAdapter;
77  import com.eviware.soapui.settings.UISettings;
78  import com.eviware.soapui.support.DocumentListenerAdapter;
79  import com.eviware.soapui.support.ListDataChangeListener;
80  import com.eviware.soapui.support.StringUtils;
81  import com.eviware.soapui.support.UISupport;
82  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
83  import com.eviware.soapui.support.components.JComponentInspector;
84  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
85  import com.eviware.soapui.support.components.JInspectorPanel;
86  import com.eviware.soapui.support.components.JInspectorPanelFactory;
87  import com.eviware.soapui.support.components.JUndoableTextField;
88  import com.eviware.soapui.support.components.JXToolBar;
89  import com.eviware.soapui.support.components.SimpleForm;
90  import com.eviware.soapui.support.editor.xml.support.AbstractXmlDocument;
91  import com.eviware.soapui.support.jdbc.JdbcUtils;
92  import com.eviware.soapui.support.log.JLogList;
93  import com.eviware.soapui.support.propertyexpansion.PropertyExpansionPopupListener;
94  import com.eviware.soapui.support.swing.JXEditAreaPopupMenu;
95  import com.eviware.soapui.support.types.StringToStringMap;
96  import com.eviware.soapui.support.xml.JXEditTextArea;
97  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
98  
99  public class JdbcRequestTestStepDesktopPanel extends ModelItemDesktopPanel<JdbcRequestTestStep> implements
100 		SubmitListener
101 {
102 	private final static Logger log = Logger.getLogger( AbstractHttpRequestDesktopPanel.class );
103 	protected JPanel configPanel;
104 	private JButton addAssertionButton;
105 	protected JInspectorPanel inspectorPanel;
106 	protected JdbcRequestTestStep jdbcRequestTestStep;
107 	protected JdbcRequestTestStepConfig jdbcRequestTestStepConfig;
108 	protected JComponentInspector<?> assertionInspector;
109 	protected AssertionsPanel assertionsPanel;
110 	private InternalAssertionsListener assertionsListener = new InternalAssertionsListener();
111 	private InternalTestMonitorListener testMonitorListener = new InternalTestMonitorListener();
112 	protected JComponent requestEditor;
113 	protected ModelItemXmlEditor<?, ?> responseEditor;
114 	protected JPanel panel;
115 	protected SimpleForm configForm;
116 	protected static final String DRIVER_FIELD = "Driver";
117 	protected static final String CONNSTR_FIELD = "Connection String";
118 	protected static final String PASS_FIELD = "Password";
119 	public static final String QUERY_FIELD = "SQL Query";
120 	protected static final String STOREDPROCEDURE_FIELD = "Stored Procedure";
121 	protected static final String DATA_CONNECTION_FIELD = "Connection";
122 
123 	protected static final String QUERY_ELEMENT = "query";
124 	protected static final String STOREDPROCEDURE_ELEMENT = "stored-procedure";
125 	protected Connection connection;
126 	protected JXEditTextArea queryArea;
127 	protected JCheckBox isStoredProcedureCheckBox;
128 	protected JTextField driverTextField;
129 	protected JTextField connStrTextField;
130 	protected JButton testConnectionButton;
131 	protected JPasswordField passField;
132 	private Submit submit;
133 	private SubmitAction submitAction;
134 	protected JButton submitButton;
135 	private JToggleButton tabsButton;
136 	private JTabbedPane requestTabs;
137 	private JPanel requestTabPanel;
138 	private boolean responseHasFocus;
139 	private JSplitPane requestSplitPane;
140 	private JEditorStatusBarWithProgress statusBar;
141 	private JButton cancelButton;
142 	private JButton splitButton;
143 	protected JComponent propertiesTableComponent;
144 	private JComponentInspector<?> logInspector;
145 	protected JLogList logArea;
146 	private long startTime;
147 	private SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
148 	protected JButton reconfigureConnPropertiesButton;
149 	protected PropertyHolderTable propertyHolderTable;
150 
151 	public JdbcRequestTestStepDesktopPanel( JdbcRequestTestStep modelItem )
152 	{
153 		super( modelItem );
154 		jdbcRequestTestStep = modelItem;
155 		initConfig();
156 		initContent();
157 
158 		SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
159 		setEnabled( !SoapUI.getTestMonitor().hasRunningTest( jdbcRequestTestStep.getTestCase() ) );
160 
161 		jdbcRequestTestStep.addAssertionsListener( assertionsListener );
162 	}
163 
164 	protected void initConfig()
165 	{
166 		jdbcRequestTestStepConfig = jdbcRequestTestStep.getJdbcRequestTestStepConfig();
167 	}
168 
169 	protected JComponent buildContent()
170 	{
171 		requestSplitPane = UISupport.createHorizontalSplit();
172 		requestSplitPane.setResizeWeight( 0.5 );
173 		requestSplitPane.setBorder( null );
174 
175 		JComponent content;
176 		submitAction = new SubmitAction();
177 		submitButton = createActionButton( submitAction, true );
178 		submitButton.setEnabled( enableSubmit() );
179 
180 		cancelButton = createActionButton( new CancelAction(), false );
181 		tabsButton = new JToggleButton( new ChangeToTabsAction() );
182 		tabsButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
183 		splitButton = createActionButton( new ChangeSplitPaneOrientationAction( requestSplitPane ), true );
184 
185 		addAssertionButton = UISupport.createToolbarButton( new AddAssertionAction( jdbcRequestTestStep ) );
186 		addAssertionButton.setEnabled( true );
187 
188 		requestTabs = new JTabbedPane();
189 		requestTabs.addChangeListener( new ChangeListener()
190 		{
191 
192 			public void stateChanged( ChangeEvent e )
193 			{
194 				SwingUtilities.invokeLater( new Runnable()
195 				{
196 
197 					public void run()
198 					{
199 						int ix = requestTabs.getSelectedIndex();
200 						if( ix == 0 )
201 							requestEditor.requestFocus();
202 						else if( ix == 1 && responseEditor != null )
203 							responseEditor.requestFocus();
204 					}
205 				} );
206 			}
207 		} );
208 
209 		addFocusListener( new FocusAdapter()
210 		{
211 
212 			@Override
213 			public void focusGained( FocusEvent e )
214 			{
215 				if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
216 					responseEditor.requestFocusInWindow();
217 				else
218 					requestEditor.requestFocusInWindow();
219 			}
220 		} );
221 
222 		requestTabPanel = UISupport.createTabPanel( requestTabs, true );
223 
224 		requestEditor = buildRequestConfigPanel();
225 		responseEditor = buildResponseEditor();
226 		if( jdbcRequestTestStep.getSettings().getBoolean( UISettings.START_WITH_REQUEST_TABS ) )
227 		{
228 			requestTabs.addTab( "Request", requestEditor );
229 			if( responseEditor != null )
230 				requestTabs.addTab( "Response", responseEditor );
231 			tabsButton.setSelected( true );
232 			splitButton.setEnabled( false );
233 
234 			content = requestTabPanel;
235 		}
236 		else
237 		{
238 			requestSplitPane.setTopComponent( requestEditor );
239 			requestSplitPane.setBottomComponent( responseEditor );
240 			requestSplitPane.setDividerLocation( 0.5 );
241 			content = requestSplitPane;
242 		}
243 
244 		inspectorPanel = JInspectorPanelFactory.build( content );
245 		inspectorPanel.setDefaultDividerLocation( 0.7F );
246 		add( buildToolbar(), BorderLayout.NORTH );
247 		add( inspectorPanel.getComponent(), BorderLayout.CENTER );
248 		assertionsPanel = buildAssertionsPanel();
249 
250 		assertionInspector = new JComponentInspector<JComponent>( assertionsPanel, "Assertions ("
251 				+ getModelItem().getAssertionCount() + ")", "Assertions for this Test Request", true );
252 
253 		inspectorPanel.addInspector( assertionInspector );
254 		logInspector = new JComponentInspector<JComponent>( buildLogPanel(), "Request Log (0)", "Log of requests", true );
255 		inspectorPanel.addInspector( logInspector );
256 		inspectorPanel.setCurrentInspector( "Assertions" );
257 
258 		updateStatusIcon();
259 
260 		return inspectorPanel.getComponent();
261 	}
262 
263 	protected JComponent buildRequestConfigPanel()
264 	{
265 		configPanel = UISupport.addTitledBorder( new JPanel( new BorderLayout() ), "Configuration" );
266 		if( panel == null )
267 		{
268 			panel = new JPanel( new BorderLayout() );
269 			configForm = new SimpleForm();
270 			createSimpleJdbcConfigForm();
271 			addStoreProcedureChangeListener();
272 
273 			panel.add( new JScrollPane( configForm.getPanel() ) );
274 		}
275 		configPanel.add( panel, BorderLayout.CENTER );
276 
277 		propertiesTableComponent = buildProperties();
278 		JSplitPane split = UISupport.createVerticalSplit( propertiesTableComponent, configPanel );
279 		split.setDividerLocation( 120 );
280 
281 		return split;
282 
283 	}
284 
285 	protected void initContent()
286 	{
287 		jdbcRequestTestStep.getJdbcRequest().addSubmitListener( this );
288 
289 		add( buildContent(), BorderLayout.CENTER );
290 		add( buildToolbar(), BorderLayout.NORTH );
291 		add( buildStatusLabel(), BorderLayout.SOUTH );
292 
293 		setPreferredSize( new Dimension( 600, 500 ) );
294 
295 		addFocusListener( new FocusAdapter()
296 		{
297 
298 			@Override
299 			public void focusGained( FocusEvent e )
300 			{
301 				if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
302 					responseEditor.requestFocusInWindow();
303 				else
304 					requestEditor.requestFocusInWindow();
305 			}
306 		} );
307 	}
308 
309 	protected JComponent buildStatusLabel()
310 	{
311 		statusBar = new JEditorStatusBarWithProgress();
312 		statusBar.setBorder( BorderFactory.createEmptyBorder( 1, 0, 0, 0 ) );
313 
314 		return statusBar;
315 	}
316 
317 	protected JComponent buildProperties()
318 	{
319 		propertyHolderTable = new PropertyHolderTable( getModelItem() ){
320 			protected JTable buildPropertiesTable()
321 			{
322 				propertiesModel = new DefaultPropertyTableHolderModel( holder )
323 				{
324 					@Override
325 					public String[] getPropertyNames()
326 					{
327 						List<String> propertyNamesList = new ArrayList<String>();
328 						for( String name : holder.getPropertyNames() )
329 						{
330 							if( name.equals( "ResponseAsXML" ) )
331 							{
332 								continue;
333 							}
334 							propertyNamesList.add( name );
335 						}
336 						return propertyNamesList.toArray( new String[propertyNamesList.size()] );
337 					}
338 				};
339 				propertiesTable = new PropertiesHolderJTable();
340 				propertiesTable.setSurrendersFocusOnKeystroke( true );
341 
342 				propertiesTable.putClientProperty( "terminateEditOnFocusLost", Boolean.TRUE );
343 				propertiesTable.getSelectionModel().addListSelectionListener( new ListSelectionListener()
344 				{
345 					public void valueChanged( ListSelectionEvent e )
346 					{
347 						int selectedRow = propertiesTable.getSelectedRow();
348 						if( removePropertyAction != null )
349 							removePropertyAction.setEnabled( selectedRow != -1 );
350 
351 						if( movePropertyUpAction != null )
352 							movePropertyUpAction.setEnabled( selectedRow > 0 );
353 
354 						if( movePropertyDownAction != null )
355 							movePropertyDownAction.setEnabled( selectedRow >= 0
356 									&& selectedRow < propertiesTable.getRowCount() - 1 );
357 					}
358 				} );
359 
360 				propertiesTable.setDragEnabled( true );
361 				propertiesTable.setTransferHandler( new TransferHandler( "testProperty" ) );
362 
363 				if( getHolder().getModelItem() != null )
364 				{
365 					DropTarget dropTarget = new DropTarget( propertiesTable,
366 							new PropertyHolderTablePropertyExpansionDropTarget() );
367 					dropTarget.setDefaultActions( DnDConstants.ACTION_COPY_OR_MOVE );
368 				}
369 
370 				return propertiesTable;
371 			}
372 		};
373 
374 		JUndoableTextField textField = new JUndoableTextField( true );
375 
376 		PropertyExpansionPopupListener.enable( textField, getModelItem() );
377 		propertyHolderTable.getPropertiesTable().setDefaultEditor( String.class, new DefaultCellEditor( textField ) );
378 
379 		return propertyHolderTable;
380 	}
381 
382 	public PropertyHolderTable getPropertyHolderTable()
383 	{
384 		return propertyHolderTable;
385 	}
386 
387 	public void setPropertyHolderTable( StringToStringMap preparedProperties )
388 	{
389 		// first remove the old content
390 		String[] names = propertyHolderTable.getHolder().getPropertyNames();
391 		if( names.length > 0 )
392 		{
393 			for( String propertyName : names )
394 			{
395 				( ( MutableTestPropertyHolder )propertyHolderTable.getHolder() ).removeProperty( propertyName );
396 			}
397 		}
398 		propertyHolderTable.getPropertiesTable().removeAll();
399 		if( preparedProperties != null )
400 		{
401 			int i = 0;
402 			for( String key : preparedProperties.keySet() )
403 			{
404 				String value = preparedProperties.get( key );
405 				( ( MutableTestPropertyHolder )propertyHolderTable.getHolder() ).addProperty( key );
406 				( ( MutableTestPropertyHolder )propertyHolderTable.getHolder() ).setPropertyValue( key, value );
407 				i++ ;
408 			}
409 		}
410 	}
411 
412 	protected JComponent buildToolbar()
413 	{
414 		JXToolBar toolbar = UISupport.createToolbar();
415 
416 		toolbar.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
417 
418 		toolbar.addFixed( submitButton );
419 		toolbar.add( cancelButton );
420 		toolbar.addFixed( addAssertionButton );
421 
422 		toolbar.add( Box.createHorizontalGlue() );
423 		toolbar.add( tabsButton );
424 		toolbar.add( splitButton );
425 		toolbar.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.JDBCSTEPEDITOR_HELP_URL ) ) );
426 		return toolbar;
427 
428 	}
429 
430 	public JdbcRequestTestStep getJdbcRequestTestStep()
431 	{
432 		return jdbcRequestTestStep;
433 	}
434 
435 	public void setQuery( String query )
436 	{
437 		if( configForm != null )
438 		{
439 			configForm.setComponentValue( QUERY_FIELD, query );
440 			jdbcRequestTestStep.setQuery( query );
441 		}
442 		else
443 		{
444 			// this.query = query;
445 			jdbcRequestTestStep.setQuery( query );
446 		}
447 	}
448 
449 	protected JComponent buildLogPanel()
450 	{
451 		logArea = new JLogList( "Request Log" );
452 
453 		logArea.getLogList().getModel().addListDataListener( new ListDataChangeListener()
454 		{
455 			public void dataChanged( ListModel model )
456 			{
457 				logInspector.setTitle( "Request Log (" + model.getSize() + ")" );
458 			}
459 		} );
460 
461 		return logArea;
462 	}
463 
464 	protected AssertionsPanel buildAssertionsPanel()
465 	{
466 		return new JdbcAssertionsPanel( jdbcRequestTestStep )
467 		{
468 		};
469 	}
470 
471 	protected class JdbcAssertionsPanel extends AssertionsPanel
472 	{
473 		public JdbcAssertionsPanel( Assertable assertable )
474 		{
475 			super( assertable );
476 		}
477 	}
478 
479 	protected void createSimpleJdbcConfigForm()
480 	{
481 		configForm.addSpace( 5 );
482 		configForm.setDefaultTextFieldColumns( 50 );
483 
484 		driverTextField = configForm.appendTextField( DRIVER_FIELD, "JDBC Driver to use" );
485 		driverTextField.setText( jdbcRequestTestStep.getDriver() );
486 		PropertyExpansionPopupListener.enable( driverTextField, jdbcRequestTestStep );
487 		addDriverDocumentListener();
488 
489 		connStrTextField = configForm.appendTextField( CONNSTR_FIELD, "JDBC Driver Connection String" );
490 		connStrTextField.setText( jdbcRequestTestStep.getConnectionString() );
491 		PropertyExpansionPopupListener.enable( connStrTextField, jdbcRequestTestStep );
492 		addConnStrDocumentListener();
493 
494 		passField = configForm.appendPasswordField( PASS_FIELD, "Connection string Password" );
495 		passField.setVisible( false );
496 		passField.setText( jdbcRequestTestStep.getPassword() );
497 		addPasswordDocumentListener();
498 
499 		reconfigureConnPropertiesButton = new JButton();
500 		configForm.addLeftComponent( reconfigureConnPropertiesButton );
501 		reconfigureConnPropertiesButton.setVisible( false );
502 		configForm.appendSeparator();
503 
504 		testConnectionButton = configForm.appendButton( "TestConnection", "Test selected database connection" );
505 		testConnectionButton.setAction( new TestConnectionAction() );
506 		testConnectionButton.setEnabled( enableTestConnection() );
507 		submitButton.setEnabled( enableSubmit() );
508 
509 		queryArea = JXEditTextArea.createSqlEditor();
510 		JXEditAreaPopupMenu.add( queryArea );
511 		PropertyExpansionPopupListener.enable( queryArea, jdbcRequestTestStep );
512 		queryArea.setText( jdbcRequestTestStep.getQuery() );
513 		JScrollPane scrollPane = new JScrollPane( queryArea );
514 		scrollPane.setPreferredSize( new Dimension( 400, 150 ) );
515 		configForm.append( QUERY_FIELD, scrollPane );
516 		queryArea.getDocument().addDocumentListener( new DocumentListenerAdapter()
517 		{
518 
519 			@Override
520 			public void update( Document document )
521 			{
522 				jdbcRequestTestStep.setQuery( queryArea.getText() );
523 				submitButton.setEnabled( enableSubmit() );
524 			}
525 		} );
526 
527 		isStoredProcedureCheckBox = configForm.appendCheckBox( STOREDPROCEDURE_FIELD,
528 				"Select if this is a stored procedure", jdbcRequestTestStep.isStoredProcedure() );
529 	}
530 
531 	protected void addPasswordDocumentListener()
532 	{
533 		passField.getDocument().addDocumentListener( new DocumentListenerAdapter()
534 		{
535 
536 			@Override
537 			public void update( Document document )
538 			{
539 				jdbcRequestTestStep.setPassword( configForm.getComponentValue( PASS_FIELD ) );
540 				testConnectionButton.setEnabled( enableTestConnection() );
541 				submitButton.setEnabled( enableSubmit() );
542 			}
543 		} );
544 	}
545 
546 	protected void addConnStrDocumentListener()
547 	{
548 		connStrTextField.getDocument().addDocumentListener( new DocumentListenerAdapter()
549 		{
550 			@Override
551 			public void update( Document document )
552 			{
553 				jdbcRequestTestStep.setConnectionString( configForm.getComponentValue( CONNSTR_FIELD ) );
554 				testConnectionButton.setEnabled( enableTestConnection() );
555 				submitButton.setEnabled( enableSubmit() );
556 			}
557 		} );
558 	}
559 
560 	protected void addDriverDocumentListener()
561 	{
562 		driverTextField.getDocument().addDocumentListener( new DocumentListenerAdapter()
563 		{
564 			@Override
565 			public void update( Document document )
566 			{
567 				jdbcRequestTestStep.setDriver( configForm.getComponentValue( DRIVER_FIELD ) );
568 				testConnectionButton.setEnabled( enableTestConnection() );
569 				submitButton.setEnabled( enableSubmit() );
570 			}
571 		} );
572 	}
573 
574 	protected void addStoreProcedureChangeListener()
575 	{
576 		isStoredProcedureCheckBox.addItemListener( new ItemListener()
577 		{
578 			public void itemStateChanged( ItemEvent arg0 )
579 			{
580 				jdbcRequestTestStep.setStoredProcedure( ( ( JCheckBox )arg0.getSource() ).isSelected() );
581 				SwingUtilities.invokeLater( new Runnable()
582 				{
583 
584 					public void run()
585 					{
586 						if( UISupport.confirm( "Would you like to empty current sql and properties?",
587 								"Reset query and properties" ) )
588 						{
589 							queryArea.setText( "" );
590 							( ( JdbcRequestTestStep )getPropertyHolderTable().getHolder() ).removeAllProperties();
591 						}
592 					}
593 				} );
594 			}
595 		} );
596 	}
597 
598 	protected boolean enableTestConnection()
599 	{
600 		if( StringUtils.isNullOrEmpty( jdbcRequestTestStep.getDriver() )
601 				|| StringUtils.isNullOrEmpty( jdbcRequestTestStep.getConnectionString() )
602 				|| ( JdbcRequestTestStep.isNeededPassword( jdbcRequestTestStep.getConnectionString() ) && StringUtils
603 						.isNullOrEmpty( jdbcRequestTestStep.getPassword() ) ) )
604 		{
605 			return false;
606 		}
607 		else
608 		{
609 			if( jdbcRequestTestStep.getConnectionString().contains( JdbcRequestTestStep.PASS_TEMPLATE ) )
610 			{
611 				return !StringUtils.isNullOrEmpty( jdbcRequestTestStep.getPassword() );
612 			}
613 			else
614 			{
615 				return true;
616 			}
617 		}
618 	}
619 
620 	protected boolean enableSubmit()
621 	{
622 		return enableTestConnection() && !StringUtils.isNullOrEmpty( jdbcRequestTestStep.getQuery() );
623 	}
624 
625 	protected ModelItemXmlEditor<?, ?> buildResponseEditor()
626 	{
627 		return new JdbcResponseMessageEditor();
628 	}
629 
630 	public class JdbcResponseMessageEditor extends ResponseMessageXmlEditor<JdbcRequestTestStep, JdbcResponseDocument>
631 	{
632 		public JdbcResponseMessageEditor()
633 		{
634 			super( new JdbcResponseDocument(), jdbcRequestTestStep );
635 		}
636 	}
637 
638 	public boolean dependsOn( ModelItem modelItem )
639 	{
640 		return modelItem == getModelItem() || modelItem == getModelItem().getTestCase()
641 				|| modelItem == getModelItem().getTestCase().getTestSuite()
642 				|| modelItem == getModelItem().getTestCase().getTestSuite().getProject();
643 	}
644 
645 	public boolean onClose( boolean canCancel )
646 	{
647 		configPanel.removeAll();
648 
649 		SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
650 		jdbcRequestTestStep.removeAssertionsListener( assertionsListener );
651 		jdbcRequestTestStep.getJdbcRequest().removeSubmitListener( this );
652 
653 		responseEditor.release();
654 		assertionsPanel.release();
655 		inspectorPanel.release();
656 		propertyHolderTable.release();
657 		
658 		return release();
659 	}
660 
661 	public class JdbcResponseDocument extends AbstractXmlDocument implements PropertyChangeListener
662 	{
663 		public JdbcResponseDocument()
664 		{
665 			jdbcRequestTestStep.addPropertyChangeListener( JdbcRequestTestStep.RESPONSE_PROPERTY, this );
666 		}
667 
668 		public void propertyChange( PropertyChangeEvent evt )
669 		{
670 			fireXmlChanged( evt.getOldValue() == null ? null : ( ( JdbcResponse )evt.getOldValue() ).getContentAsString(),
671 					getXml() );
672 		}
673 
674 		public String getXml()
675 		{
676 			JdbcResponse response = jdbcRequestTestStep.getJdbcRequest().getResponse();
677 			return response == null ? null : response.getContentAsString();
678 		}
679 
680 		public void setXml( String xml )
681 		{
682 			if( jdbcRequestTestStep.getJdbcRequest().getResponse() != null )
683 				jdbcRequestTestStep.getJdbcRequest().getResponse().setContentAsString( xml );
684 		}
685 
686 		public void release()
687 		{
688 			super.release();
689 			jdbcRequestTestStep.removePropertyChangeListener( JdbcRequestTestStep.RESPONSE_PROPERTY, this );
690 		}
691 	}
692 
693 	public class TestConnectionAction extends AbstractAction
694 	{
695 		public TestConnectionAction()
696 		{
697 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
698 			putValue( Action.SHORT_DESCRIPTION, "Test the current Connection" );
699 
700 			setEnabled( false );
701 		}
702 
703 		public void actionPerformed( ActionEvent arg0 )
704 		{
705 			try
706 			{
707 				JdbcUtils.testConnection( getModelItem(), jdbcRequestTestStep.getDriver(), jdbcRequestTestStep
708 						.getConnectionString(), jdbcRequestTestStep.getPassword() );
709 				UISupport.showInfoMessage( "The Connection Successfully Tested" );
710 			}
711 			catch( Exception e )
712 			{
713 				UISupport.showErrorMessage( "Can't get the Connection for specified properties; " + e.toString() );
714 			}
715 		}
716 	}
717 
718 	private class InternalTestMonitorListener extends TestMonitorListenerAdapter
719 	{
720 		public void loadTestFinished( LoadTestRunner runner )
721 		{
722 			setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
723 		}
724 
725 		public void loadTestStarted( LoadTestRunner runner )
726 		{
727 			if( runner.getLoadTest().getTestCase() == getModelItem().getTestCase() )
728 				setEnabled( false );
729 		}
730 
731 		public void testCaseFinished( TestCaseRunner runner )
732 		{
733 			setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
734 		}
735 
736 		public void testCaseStarted( TestCaseRunner runner )
737 		{
738 			if( runner.getTestCase() == getModelItem().getTestCase() )
739 				setEnabled( false );
740 		}
741 	}
742 
743 	public class SubmitAction extends AbstractAction
744 	{
745 		public SubmitAction()
746 		{
747 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/submit_request.gif" ) );
748 			putValue( Action.SHORT_DESCRIPTION, "Submit request to specified endpoint URL" );
749 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt ENTER" ) );
750 		}
751 
752 		public void actionPerformed( ActionEvent e )
753 		{
754 			onSubmit();
755 		}
756 	}
757 
758 	protected void onSubmit()
759 	{
760 		if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
761 		{
762 			if( UISupport.confirm( "Cancel current request?", "Submit Request" ) )
763 			{
764 				submit.cancel();
765 			}
766 			else
767 				return;
768 		}
769 
770 		try
771 		{
772 			submit = doSubmit();
773 		}
774 		catch( SubmitException e1 )
775 		{
776 			SoapUI.logError( e1 );
777 		}
778 	}
779 
780 	protected Submit doSubmit() throws SubmitException
781 	{
782 		return jdbcRequestTestStep.getJdbcRequest().submit( new WsdlTestRunContext( getModelItem() ), true );
783 	}
784 
785 	private final class ChangeToTabsAction extends AbstractAction
786 	{
787 		public ChangeToTabsAction()
788 		{
789 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/toggle_tabs.gif" ) );
790 			putValue( Action.SHORT_DESCRIPTION, "Toggles to tab-based layout" );
791 		}
792 
793 		public void actionPerformed( ActionEvent e )
794 		{
795 			if( splitButton.isEnabled() )
796 			{
797 				splitButton.setEnabled( false );
798 				removeContent( requestSplitPane );
799 				setContent( requestTabPanel );
800 				requestTabs.addTab( "Request", requestEditor );
801 
802 				if( responseEditor != null )
803 					requestTabs.addTab( "Response", responseEditor );
804 
805 				if( responseHasFocus )
806 				{
807 					requestTabs.setSelectedIndex( 1 );
808 					requestEditor.requestFocus();
809 				}
810 				requestTabs.repaint();
811 			}
812 			else
813 			{
814 				int selectedIndex = requestTabs.getSelectedIndex();
815 
816 				splitButton.setEnabled( true );
817 				removeContent( requestTabPanel );
818 				setContent( requestSplitPane );
819 				requestSplitPane.setTopComponent( requestEditor );
820 				if( responseEditor != null )
821 					requestSplitPane.setBottomComponent( responseEditor );
822 				requestSplitPane.setDividerLocation( 0.5 );
823 
824 				if( selectedIndex == 0 || responseEditor == null )
825 					requestEditor.requestFocus();
826 				else
827 					responseEditor.requestFocus();
828 				requestSplitPane.repaint();
829 			}
830 
831 			revalidate();
832 		}
833 	}
834 
835 	public void setContent( JComponent content )
836 	{
837 		inspectorPanel.setContentComponent( content );
838 	}
839 
840 	public void removeContent( JComponent content )
841 	{
842 		inspectorPanel.setContentComponent( null );
843 	}
844 
845 	private class CancelAction extends AbstractAction
846 	{
847 		public CancelAction()
848 		{
849 			super();
850 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/cancel_request.gif" ) );
851 			putValue( Action.SHORT_DESCRIPTION, "Aborts ongoing request" );
852 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt X" ) );
853 		}
854 
855 		public void actionPerformed( ActionEvent e )
856 		{
857 			onCancel();
858 		}
859 	}
860 
861 	protected void onCancel()
862 	{
863 		if( submit == null )
864 			return;
865 
866 		cancelButton.setEnabled( false );
867 		submit.cancel();
868 		setEnabled( true );
869 		submit = null;
870 	}
871 
872 	public void setEnabled( boolean enabled )
873 	{
874 		if( responseEditor != null )
875 			responseEditor.setEditable( enabled );
876 
877 		submitButton.setEnabled( enabled );
878 		addAssertionButton.setEnabled( enabled );
879 		driverTextField.setEnabled( enabled );
880 		connStrTextField.setEnabled( enabled );
881 		passField.setEnabled( enabled );
882 		queryArea.setEnabledAndEditable( enabled );
883 		isStoredProcedureCheckBox.setEnabled( enabled );
884 		propertiesTableComponent.setEnabled( enabled );
885 		testConnectionButton.setEnabled( enabled );
886 
887 		statusBar.setIndeterminate( !enabled );
888 	}
889 
890 	public void afterSubmit( Submit submit, SubmitContext context )
891 	{
892 		if( submit.getRequest() != jdbcRequestTestStep.getJdbcRequest() )
893 			return;
894 
895 		Status status = submit.getStatus();
896 		JdbcResponse response = ( JdbcResponse )submit.getResponse();
897 		if( status == Status.FINISHED )
898 		{
899 			jdbcRequestTestStep.setResponse( response, context );
900 		}
901 
902 		cancelButton.setEnabled( false );
903 		setEnabled( true );
904 
905 		String message = null;
906 		String infoMessage = null;
907 		String requestName = jdbcRequestTestStep.getName();
908 
909 		if( status == Status.CANCELED )
910 		{
911 			message = "CANCELED";
912 			infoMessage = "[" + requestName + "] - CANCELED";
913 		}
914 		else
915 		{
916 			if( status == Status.ERROR || response == null )
917 			{
918 				message = "Error getting response; " + submit.getError();
919 				infoMessage = "Error getting response for [" + requestName + "]; " + submit.getError();
920 			}
921 			else
922 			{
923 				message = "response time: " + response.getTimeTaken() + "ms (" + response.getContentLength() + " bytes)";
924 				infoMessage = "Got response for [" + requestName + "] in " + response.getTimeTaken() + "ms ("
925 						+ response.getContentLength() + " bytes)";
926 
927 				if( !splitButton.isEnabled() )
928 					requestTabs.setSelectedIndex( 1 );
929 
930 				responseEditor.requestFocus();
931 			}
932 		}
933 
934 		logMessages( message, infoMessage );
935 
936 		if( getModelItem().getSettings().getBoolean( UISettings.AUTO_VALIDATE_RESPONSE ) )
937 			responseEditor.getSourceEditor().validate();
938 
939 		JdbcRequestTestStepDesktopPanel.this.submit = null;
940 
941 		updateStatusIcon();
942 	}
943 
944 	protected void logMessages( String message, String infoMessage )
945 	{
946 		log.info( infoMessage );
947 		statusBar.setInfo( message );
948 		logArea.addLine( sdf.format( new Date( startTime ) ) + " - " + message );
949 	}
950 
951 	public boolean beforeSubmit( Submit submit, SubmitContext context )
952 	{
953 		if( submit.getRequest() != jdbcRequestTestStep.getJdbcRequest() )
954 			return true;
955 
956 		setEnabled( false );
957 		cancelButton.setEnabled( JdbcRequestTestStepDesktopPanel.this.submit != null );
958 		return true;
959 	}
960 
961 	public void propertyChange( PropertyChangeEvent evt )
962 	{
963 		super.propertyChange( evt );
964 
965 		if( evt.getPropertyName().equals( JdbcRequestTestStep.STATUS_PROPERTY ) )
966 			updateStatusIcon();
967 	}
968 
969 	private final class InternalAssertionsListener implements AssertionsListener
970 	{
971 		public void assertionAdded( TestAssertion assertion )
972 		{
973 			assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
974 		}
975 
976 		public void assertionRemoved( TestAssertion assertion )
977 		{
978 			assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
979 		}
980 
981 		public void assertionMoved( TestAssertion assertion, int ix, int offset )
982 		{
983 			assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
984 		}
985 	}
986 
987 	private void updateStatusIcon()
988 	{
989 		AssertionStatus status = jdbcRequestTestStep.getAssertionStatus();
990 		switch( status )
991 		{
992 		case FAILED :
993 		{
994 			assertionInspector.setIcon( UISupport.createImageIcon( "/failed_assertion.gif" ) );
995 			inspectorPanel.activate( assertionInspector );
996 			break;
997 		}
998 		case UNKNOWN :
999 		{
1000 			assertionInspector.setIcon( UISupport.createImageIcon( "/unknown_assertion.gif" ) );
1001 			break;
1002 		}
1003 		case VALID :
1004 		{
1005 			assertionInspector.setIcon( UISupport.createImageIcon( "/valid_assertion.gif" ) );
1006 			inspectorPanel.deactivate();
1007 			break;
1008 		}
1009 		}
1010 	}
1011 }