1
2
3
4
5 package com.eviware.soapui.impl.wsdl.panels.teststeps.amf;
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.FocusListener;
15 import java.beans.PropertyChangeEvent;
16 import java.beans.PropertyChangeListener;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.List;
20
21 import javax.swing.AbstractAction;
22 import javax.swing.Action;
23 import javax.swing.BorderFactory;
24 import javax.swing.Box;
25 import javax.swing.DefaultCellEditor;
26 import javax.swing.JButton;
27 import javax.swing.JComponent;
28 import javax.swing.JLabel;
29 import javax.swing.JPanel;
30 import javax.swing.JSplitPane;
31 import javax.swing.JTabbedPane;
32 import javax.swing.JTable;
33 import javax.swing.JTextField;
34 import javax.swing.JToggleButton;
35 import javax.swing.SwingUtilities;
36 import javax.swing.TransferHandler;
37 import javax.swing.event.ChangeEvent;
38 import javax.swing.event.ChangeListener;
39 import javax.swing.event.ListSelectionEvent;
40 import javax.swing.event.ListSelectionListener;
41 import javax.swing.text.Document;
42
43 import org.apache.log4j.Logger;
44
45 import com.eviware.soapui.SoapUI;
46 import com.eviware.soapui.config.AMFRequestTestStepConfig;
47 import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
48 import com.eviware.soapui.impl.support.components.ModelItemXmlEditor;
49 import com.eviware.soapui.impl.support.components.RequestMessageXmlEditor;
50 import com.eviware.soapui.impl.support.components.ResponseMessageXmlEditor;
51 import com.eviware.soapui.impl.support.panels.AbstractHttpRequestDesktopPanel;
52 import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
53 import com.eviware.soapui.impl.wsdl.panels.teststeps.AssertionsPanel;
54 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.DefaultPropertyTableHolderModel;
55 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
56 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditorModel;
57 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
58 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
59 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
60 import com.eviware.soapui.impl.wsdl.teststeps.AMFRequestTestStep;
61 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStepWithProperties;
62 import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
63 import com.eviware.soapui.model.ModelItem;
64 import com.eviware.soapui.model.iface.Submit;
65 import com.eviware.soapui.model.iface.SubmitContext;
66 import com.eviware.soapui.model.iface.SubmitListener;
67 import com.eviware.soapui.model.iface.Request.SubmitException;
68 import com.eviware.soapui.model.iface.Submit.Status;
69 import com.eviware.soapui.model.settings.Settings;
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.StringUtils;
80 import com.eviware.soapui.support.UISupport;
81 import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
82 import com.eviware.soapui.support.components.JComponentInspector;
83 import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
84 import com.eviware.soapui.support.components.JInspectorPanel;
85 import com.eviware.soapui.support.components.JInspectorPanelFactory;
86 import com.eviware.soapui.support.components.JUndoableTextField;
87 import com.eviware.soapui.support.components.JXToolBar;
88 import com.eviware.soapui.support.components.SimpleForm;
89 import com.eviware.soapui.support.editor.Editor;
90 import com.eviware.soapui.support.editor.EditorView;
91 import com.eviware.soapui.support.editor.support.AbstractEditorView;
92 import com.eviware.soapui.support.editor.xml.support.AbstractXmlDocument;
93 import com.eviware.soapui.support.propertyexpansion.PropertyExpansionPopupListener;
94 import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
95 import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
96 import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
97 import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
98
99 @SuppressWarnings( "serial" )
100 public class AMFRequestTestStepDesktopPanel extends ModelItemDesktopPanel<AMFRequestTestStep> implements SubmitListener
101 {
102 private static final String ENDPOINT = "Endpoint";
103 private static final String AMF_CALL = "AMF Call";
104 private final static Logger log = Logger.getLogger( AbstractHttpRequestDesktopPanel.class );
105 private JPanel configPanel;
106 private JButton addAssertionButton;
107 private JInspectorPanel inspectorPanel;
108 private AMFRequestTestStep amfRequestTestStep;
109 protected AMFRequestTestStepConfig amfRequestTestStepConfig;
110 private JComponentInspector<?> assertionInspector;
111 private AssertionsPanel assertionsPanel;
112 private InternalAssertionsListener assertionsListener = new InternalAssertionsListener();
113 private InternalTestMonitorListener testMonitorListener = new InternalTestMonitorListener();
114 private JComponent requestEditor;
115 private ModelItemXmlEditor<?, ?> responseEditor;
116 private Submit submit;
117 private JButton submitButton;
118 private JToggleButton tabsButton;
119 private JTabbedPane requestTabs;
120 private JPanel requestTabPanel;
121 private boolean responseHasFocus;
122 private JSplitPane requestSplitPane;
123 private JEditorStatusBarWithProgress statusBar;
124 private JButton cancelButton;
125 private JButton splitButton;
126 private JComponent propertiesTableComponent;
127 private SoapUIScriptEngine scriptEngine;
128 private RunAction runAction = new RunAction();
129 private GroovyEditor groovyEditor;
130 private JTextField amfCallField;
131 public boolean updating;
132 SimpleForm configForm;
133 private JTextField endpointField;
134 private TestRunComponentEnabler componentEnabler;
135 protected PropertyHolderTable propertyHolderTable;
136
137 public AMFRequestTestStepDesktopPanel( AMFRequestTestStep modelItem )
138 {
139 super( modelItem );
140 amfRequestTestStep = modelItem;
141 componentEnabler = new TestRunComponentEnabler( amfRequestTestStep.getTestCase() );
142 initConfig();
143 initContent();
144
145 SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
146 setEnabled( !SoapUI.getTestMonitor().hasRunningTest( amfRequestTestStep.getTestCase() ) );
147
148 amfRequestTestStep.addAssertionsListener( assertionsListener );
149
150 scriptEngine = SoapUIScriptEngineRegistry.create( modelItem );
151 scriptEngine.setScript( amfRequestTestStep.getScript() );
152
153 }
154
155 protected void initConfig()
156 {
157 amfRequestTestStepConfig = amfRequestTestStep.getAMFRequestTestStepConfig();
158 }
159
160 private JComponent buildContent()
161 {
162 requestSplitPane = UISupport.createHorizontalSplit();
163 requestSplitPane.setResizeWeight( 0.5 );
164 requestSplitPane.setBorder( null );
165
166 JComponent content;
167 submitButton = createActionButton( new SubmitAction(), true );
168 submitButton.setEnabled( enableSubmit() );
169 cancelButton = createActionButton( new CancelAction(), false );
170 tabsButton = new JToggleButton( new ChangeToTabsAction() );
171 tabsButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
172 splitButton = createActionButton( new ChangeSplitPaneOrientationAction( requestSplitPane ), true );
173
174 addAssertionButton = UISupport.createToolbarButton( new AddAssertionAction( amfRequestTestStep ) );
175 addAssertionButton.setEnabled( true );
176
177 requestTabs = new JTabbedPane();
178 requestTabs.setTabPlacement( JTabbedPane.LEFT );
179 requestTabs.addChangeListener( new ChangeListener()
180 {
181
182 public void stateChanged( ChangeEvent e )
183 {
184 SwingUtilities.invokeLater( new Runnable()
185 {
186
187 public void run()
188 {
189 int ix = requestTabs.getSelectedIndex();
190 if( ix == 0 )
191 requestEditor.requestFocus();
192 else if( ix == 1 && responseEditor != null )
193 responseEditor.requestFocus();
194 }
195 } );
196 }
197 } );
198
199 addFocusListener( new FocusAdapter()
200 {
201
202 @Override
203 public void focusGained( FocusEvent e )
204 {
205 if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
206 responseEditor.requestFocusInWindow();
207 else
208 requestEditor.requestFocusInWindow();
209 }
210 } );
211
212 requestTabPanel = UISupport.createTabPanel( requestTabs, true );
213
214 requestEditor = ( JComponent )buildRequestConfigPanel();
215 responseEditor = buildResponseEditor();
216 if( amfRequestTestStep.getSettings().getBoolean( UISettings.START_WITH_REQUEST_TABS ) )
217 {
218 requestTabs.addTab( "Request", requestEditor );
219 if( responseEditor != null )
220 requestTabs.addTab( "Response", responseEditor );
221 tabsButton.setSelected( true );
222 splitButton.setEnabled( false );
223
224 content = requestTabPanel;
225 }
226 else
227 {
228 requestSplitPane.setTopComponent( requestEditor );
229 requestSplitPane.setBottomComponent( responseEditor );
230 requestSplitPane.setDividerLocation( 0.5 );
231 content = requestSplitPane;
232 }
233
234 inspectorPanel = JInspectorPanelFactory.build( content );
235 inspectorPanel.setDefaultDividerLocation( 0.7F );
236 add( buildToolbar(), BorderLayout.NORTH );
237 add( inspectorPanel.getComponent(), BorderLayout.CENTER );
238 assertionsPanel = buildAssertionsPanel();
239
240 assertionInspector = new JComponentInspector<JComponent>( assertionsPanel, "Assertions ("
241 + getModelItem().getAssertionCount() + ")", "Assertions for this Test Request", true );
242
243 inspectorPanel.addInspector( assertionInspector );
244
245
246 updateStatusIcon();
247
248 return inspectorPanel.getComponent();
249 }
250
251 @SuppressWarnings( "unchecked" )
252 protected JComponent buildRequestConfigPanel()
253 {
254 ModelItemXmlEditor<?, ?> reqEditor = buildRequestEditor();
255
256 configPanel = UISupport.addTitledBorder( new JPanel( new BorderLayout() ), "Script" );
257 configPanel.add( buildToolbarButtonAndText(), BorderLayout.NORTH );
258 groovyEditor = ( GroovyEditor )UISupport.getEditorFactory().buildGroovyEditor( new ScriptStepGroovyEditorModel() );
259 configPanel.add( groovyEditor, BorderLayout.CENTER );
260 propertiesTableComponent = buildProperties();
261 final JSplitPane split = UISupport.createVerticalSplit( propertiesTableComponent, configPanel );
262 split.setDividerLocation( 120 );
263 reqEditor.addEditorView( ( EditorView )new AbstractEditorView<AMFRequestDocument>( "AMF",
264 ( Editor<AMFRequestDocument> )reqEditor, "amf" )
265 {
266 @Override
267 public JComponent buildUI()
268 {
269 return split;
270 }
271 } );
272 reqEditor.selectView( 1 );
273 return reqEditor;
274 }
275
276 private JComponent buildToolbarButtonAndText()
277 {
278 JXToolBar toolBar = UISupport.createToolbar();
279 JButton runButton = UISupport.createToolbarButton( runAction );
280 toolBar.add( runButton );
281 toolBar.add( Box.createHorizontalGlue() );
282 JLabel label = new JLabel( "<html>Script is invoked with <code>log</code>, <code>context</code> "
283 + ", <code>parameters</code> and <code>amfHeaders</code> variables</html>" );
284 label.setToolTipText( label.getText() );
285 label.setMinimumSize( label.getPreferredSize() );
286 label.setMaximumSize( label.getPreferredSize() );
287
288 toolBar.add( label );
289 toolBar.addRelatedGap();
290 toolBar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.GROOVYSTEPEDITOR_HELP_URL ) ) );
291
292 componentEnabler.add( runButton );
293
294 return toolBar;
295 }
296
297 protected JComponent buildToolbar()
298 {
299
300 JPanel panel = new JPanel( new BorderLayout() );
301 panel.add( buildToolbar1(), BorderLayout.NORTH );
302 panel.add( buildToolbar2(), BorderLayout.SOUTH );
303 return panel;
304
305 }
306
307 protected void initContent()
308 {
309 amfRequestTestStep.getAMFRequest().addSubmitListener( this );
310
311 add( buildContent(), BorderLayout.CENTER );
312 add( buildToolbar(), BorderLayout.NORTH );
313 add( buildStatusLabel(), BorderLayout.SOUTH );
314
315 setPreferredSize( new Dimension( 600, 500 ) );
316
317 addFocusListener( new FocusAdapter()
318 {
319
320 @Override
321 public void focusGained( FocusEvent e )
322 {
323 if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
324 responseEditor.requestFocusInWindow();
325 else
326 requestEditor.requestFocusInWindow();
327 }
328 } );
329 }
330
331 protected JComponent buildStatusLabel()
332 {
333 statusBar = new JEditorStatusBarWithProgress();
334 statusBar.setBorder( BorderFactory.createEmptyBorder( 1, 0, 0, 0 ) );
335
336 return statusBar;
337 }
338
339 protected JComponent buildProperties()
340 {
341 propertyHolderTable = new PropertyHolderTable( getModelItem() )
342 {
343 protected JTable buildPropertiesTable()
344 {
345 propertiesModel = new DefaultPropertyTableHolderModel( holder )
346 {
347 @Override
348 public String[] getPropertyNames()
349 {
350 List<String> propertyNamesList = new ArrayList<String>();
351 for( String name : holder.getPropertyNames() )
352 {
353 if( name.equals( WsdlTestStepWithProperties.RESPONSE_AS_XML ) )
354 {
355 continue;
356 }
357 propertyNamesList.add( name );
358 }
359 return propertyNamesList.toArray( new String[propertyNamesList.size()] );
360 }
361 };
362 propertiesTable = new PropertiesHolderJTable();
363 propertiesTable.setSurrendersFocusOnKeystroke( true );
364
365 propertiesTable.putClientProperty( "terminateEditOnFocusLost", Boolean.TRUE );
366 propertiesTable.getSelectionModel().addListSelectionListener( new ListSelectionListener()
367 {
368 public void valueChanged( ListSelectionEvent e )
369 {
370 int selectedRow = propertiesTable.getSelectedRow();
371 if( removePropertyAction != null )
372 removePropertyAction.setEnabled( selectedRow != -1 );
373
374 if( movePropertyUpAction != null )
375 movePropertyUpAction.setEnabled( selectedRow > 0 );
376
377 if( movePropertyDownAction != null )
378 movePropertyDownAction.setEnabled( selectedRow >= 0
379 && selectedRow < propertiesTable.getRowCount() - 1 );
380 }
381 } );
382
383 propertiesTable.setDragEnabled( true );
384 propertiesTable.setTransferHandler( new TransferHandler( "testProperty" ) );
385
386 if( getHolder().getModelItem() != null )
387 {
388 DropTarget dropTarget = new DropTarget( propertiesTable,
389 new PropertyHolderTablePropertyExpansionDropTarget() );
390 dropTarget.setDefaultActions( DnDConstants.ACTION_COPY_OR_MOVE );
391 }
392
393 return propertiesTable;
394 }
395 };
396
397 JUndoableTextField textField = new JUndoableTextField( true );
398
399 PropertyExpansionPopupListener.enable( textField, getModelItem() );
400 propertyHolderTable.getPropertiesTable().setDefaultEditor( String.class, new DefaultCellEditor( textField ) );
401
402 return propertyHolderTable;
403 }
404
405 protected JComponent buildToolbar1()
406 {
407 JXToolBar toolbar = UISupport.createToolbar();
408
409 toolbar.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
410
411 toolbar.addFixed( submitButton );
412 toolbar.add( cancelButton );
413 toolbar.addFixed( addAssertionButton );
414
415 toolbar.add( Box.createHorizontalGlue() );
416 toolbar.add( tabsButton );
417 toolbar.add( splitButton );
418
419 toolbar.addFixed( UISupport
420 .createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TRANSFERSTEPEDITOR_HELP_URL ) ) );
421
422 return toolbar;
423
424 }
425
426 protected JComponent buildToolbar2()
427 {
428 JXToolBar toolbar = UISupport.createToolbar();
429
430 toolbar.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
431
432 toolbar.addLabeledFixed( ENDPOINT, addEndpointField() );
433 toolbar.addSeparator();
434 toolbar.addLabeledFixed( AMF_CALL, addAmfCallField() );
435
436 return toolbar;
437
438 }
439
440 public AMFRequestTestStep getAMFRequestTestStep()
441 {
442 return amfRequestTestStep;
443 }
444
445 protected AssertionsPanel buildAssertionsPanel()
446 {
447 return new AMFAssertionsPanel( amfRequestTestStep )
448 {
449 };
450 }
451
452 protected class AMFAssertionsPanel extends AssertionsPanel
453 {
454 public AMFAssertionsPanel( Assertable assertable )
455 {
456 super( assertable );
457 }
458 }
459
460 private JTextField addAmfCallField()
461 {
462 amfCallField = new JTextField();
463 amfCallField.setText( amfRequestTestStep.getAmfCall() );
464 amfCallField.setColumns( 20 );
465 amfCallField.setToolTipText( "object.methodName for amf method call" );
466 PropertyExpansionPopupListener.enable( amfCallField, amfRequestTestStep );
467 addAmfCallDocumentListener();
468 return amfCallField;
469 }
470
471 private JTextField addEndpointField()
472 {
473 endpointField = new JTextField();
474 endpointField.setText( amfRequestTestStep.getEndpoint() );
475 endpointField.setColumns( 35 );
476 endpointField.setToolTipText( "http to connect" );
477 PropertyExpansionPopupListener.enable( endpointField, amfRequestTestStep );
478 addEndpointCallDocumentListener();
479 return endpointField;
480 }
481
482 protected void addAmfCallDocumentListener()
483 {
484 amfCallField.getDocument().addDocumentListener( new DocumentListenerAdapter()
485 {
486 @Override
487 public void update( Document document )
488 {
489 if( !updating )
490 {
491 amfRequestTestStep.setAmfCall( amfCallField.getText() );
492 }
493 }
494 } );
495 }
496
497 protected void addEndpointCallDocumentListener()
498 {
499 endpointField.getDocument().addDocumentListener( new DocumentListenerAdapter()
500 {
501 @Override
502 public void update( Document document )
503 {
504 if( !updating )
505 {
506 amfRequestTestStep.setEndpoint( endpointField.getText() );
507 }
508 }
509 } );
510 }
511
512 protected boolean enableSubmit()
513 {
514 return !StringUtils.isNullOrEmpty( amfRequestTestStep.getEndpoint() )
515 && !StringUtils.isNullOrEmpty( amfRequestTestStep.getAmfCall() );
516 }
517
518 private class ScriptStepGroovyEditorModel implements GroovyEditorModel
519 {
520 public String[] getKeywords()
521 {
522 return new String[] { "log", "context", "property" };
523 }
524
525 public Action getRunAction()
526 {
527 return runAction;
528 }
529
530 public String getScript()
531 {
532 return amfRequestTestStep.getScript();
533 }
534
535 public void setScript( String text )
536 {
537 if( updating )
538 return;
539
540 updating = true;
541 amfRequestTestStep.setScript( text );
542 updating = false;
543 }
544
545 public Settings getSettings()
546 {
547 return SoapUI.getSettings();
548 }
549
550 public String getScriptName()
551 {
552 return null;
553 }
554
555 public void addPropertyChangeListener( PropertyChangeListener listener )
556 {
557 }
558
559 public void removePropertyChangeListener( PropertyChangeListener listener )
560 {
561 }
562
563 public ModelItem getModelItem()
564 {
565 return amfRequestTestStep;
566 }
567 }
568
569 private class RunAction extends AbstractAction
570 {
571 public RunAction()
572 {
573 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ) );
574 putValue( Action.SHORT_DESCRIPTION,
575 "Runs this script in a seperate thread using a mock testRunner and testContext" );
576 }
577
578 public void actionPerformed( ActionEvent e )
579 {
580 SoapUI.getThreadPool().execute( new Runnable()
581 {
582 public void run()
583 {
584 SubmitContext context = new WsdlTestRunContext( getModelItem() );
585 statusBar.setIndeterminate( true );
586 amfRequestTestStep.initAmfRequest( context );
587
588 if( context.getProperty( AMFRequest.AMF_SCRIPT_ERROR ) != null )
589 {
590 UISupport.showInfoMessage( ( ( Throwable )context.getProperty( AMFRequest.AMF_SCRIPT_ERROR ) )
591 .getMessage() );
592 }
593 else
594 {
595 UISupport.showInfoMessage( scriptInfo( context ) );
596
597 }
598 statusBar.setIndeterminate( false );
599 amfRequestTestStep.getAMFRequest().clearArguments();
600 }
601
602 @SuppressWarnings( "unchecked" )
603 private String scriptInfo( SubmitContext context )
604 {
605 HashMap<String, Object> parameters = ( HashMap<String, Object> )context
606 .getProperty( AMFRequest.AMF_SCRIPT_PARAMETERS );
607 HashMap<String, Object> amfHeaders = ( HashMap<String, Object> )context
608 .getProperty( AMFRequest.AMF_SCRIPT_HEADERS );
609 StringBuilder sb = new StringBuilder();
610 sb.append( "parameters " + ( parameters != null ? parameters.toString() : "" ) );
611 sb.append( "\n" );
612 sb.append( "amfHeaders " + ( amfHeaders != null ? amfHeaders.toString() : "" ) );
613 return sb.toString();
614 }
615 } );
616 }
617
618 }
619
620 protected ModelItemXmlEditor<?, ?> buildResponseEditor()
621 {
622 return new AMFResponseMessageEditor();
623 }
624
625 protected ModelItemXmlEditor<?, ?> buildRequestEditor()
626 {
627 return new AMFRequestMessageEditor();
628 }
629
630 public class AMFResponseMessageEditor extends ResponseMessageXmlEditor<AMFRequestTestStep, AMFResponseDocument>
631 {
632 public AMFResponseMessageEditor()
633 {
634 super( new AMFResponseDocument(), amfRequestTestStep );
635 }
636
637 @Override
638 public void release()
639 {
640 getDocument().release();
641 super.release();
642 }
643 }
644
645 public class AMFRequestMessageEditor extends RequestMessageXmlEditor<AMFRequestTestStep, AMFRequestDocument>
646 {
647 public AMFRequestMessageEditor()
648 {
649 super( new AMFRequestDocument(), amfRequestTestStep );
650 }
651
652 @Override
653 public void release()
654 {
655 getDocument().release();
656 super.release();
657 }
658
659 }
660
661 public boolean dependsOn( ModelItem modelItem )
662 {
663 return modelItem == getModelItem() || modelItem == getModelItem().getTestCase()
664 || modelItem == getModelItem().getTestCase().getTestSuite()
665 || modelItem == getModelItem().getTestCase().getTestSuite().getProject();
666 }
667
668 public boolean onClose( boolean canCancel )
669 {
670 configPanel.removeAll();
671 inspectorPanel.release();
672
673 requestEditor.removeAll();
674 ( ( ModelItemXmlEditor<?, ?> )requestEditor ).release();
675 responseEditor.release();
676 responseEditor.removeAll();
677 responseEditor = null;
678 assertionsPanel.release();
679 SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
680 amfRequestTestStep.removeAssertionsListener( assertionsListener );
681 amfRequestTestStep.getAMFRequest().removeSubmitListener( this );
682 componentEnabler.release();
683 groovyEditor.release();
684 amfRequestTestStep.release();
685 propertyHolderTable.release();
686 this.removeAll();
687 return release();
688 }
689
690 public class AMFResponseDocument extends AbstractXmlDocument implements PropertyChangeListener
691 {
692 public AMFResponseDocument()
693 {
694 amfRequestTestStep.addPropertyChangeListener( AMFRequestTestStep.RESPONSE_PROPERTY, this );
695 }
696
697 public void propertyChange( PropertyChangeEvent evt )
698 {
699 fireXmlChanged( evt.getOldValue() == null ? null : ( ( AMFResponse )evt.getOldValue() ).getContentAsString(),
700 getXml() );
701 }
702
703 public String getXml()
704 {
705 AMFResponse response = amfRequestTestStep.getAMFRequest().getResponse();
706 return response == null ? null : response.getResponseContentXML();
707 }
708
709 public void setXml( String xml )
710 {
711 if( amfRequestTestStep.getAMFRequest().getResponse() != null )
712 amfRequestTestStep.getAMFRequest().getResponse().setResponseContentXML( xml );
713 }
714
715 public void release()
716 {
717 super.release();
718 amfRequestTestStep.removePropertyChangeListener( AMFRequestTestStep.RESPONSE_PROPERTY, this );
719 }
720 }
721
722 public class AMFRequestDocument extends AbstractXmlDocument implements PropertyChangeListener
723 {
724 public AMFRequestDocument()
725 {
726 amfRequestTestStep.addPropertyChangeListener( AMFRequestTestStep.REQUEST_PROPERTY, this );
727 }
728
729 public void propertyChange( PropertyChangeEvent evt )
730 {
731 fireXmlChanged( evt.getOldValue() == null ? null : ( ( AMFRequest )evt.getOldValue() ).requestAsXML(),
732 getXml() );
733 }
734
735 public String getXml()
736 {
737 AMFRequest request = amfRequestTestStep.getAMFRequest();
738 return request == null ? null : request.requestAsXML();
739 }
740
741 public void setXml( String xml )
742 {
743 }
744
745 public void release()
746 {
747 super.release();
748 amfRequestTestStep.removePropertyChangeListener( AMFRequestTestStep.REQUEST_PROPERTY, this );
749 }
750 }
751
752 private class InternalTestMonitorListener extends TestMonitorListenerAdapter
753 {
754 public void loadTestFinished( LoadTestRunner runner )
755 {
756 setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
757 }
758
759 public void loadTestStarted( LoadTestRunner runner )
760 {
761 if( runner.getLoadTest().getTestCase() == getModelItem().getTestCase() )
762 setEnabled( false );
763 }
764
765 public void testCaseFinished( TestCaseRunner runner )
766 {
767 setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
768 }
769
770 public void testCaseStarted( TestCaseRunner runner )
771 {
772 if( runner.getTestCase() == getModelItem().getTestCase() )
773 setEnabled( false );
774 }
775 }
776
777 public class SubmitAction extends AbstractAction
778 {
779 public SubmitAction()
780 {
781 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/submit_request.gif" ) );
782 putValue( Action.SHORT_DESCRIPTION, "Submit request to specified endpoint URL" );
783 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt ENTER" ) );
784 }
785
786 public void actionPerformed( ActionEvent e )
787 {
788 onSubmit();
789 }
790 }
791
792 protected void onSubmit()
793 {
794 if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
795 {
796 if( UISupport.confirm( "Cancel current request?", "Submit Request" ) )
797 {
798 submit.cancel();
799 }
800 else
801 return;
802 }
803
804 try
805 {
806 submit = doSubmit();
807 }
808 catch( SubmitException e1 )
809 {
810 SoapUI.logError( e1 );
811 }
812 }
813
814 protected Submit doSubmit() throws SubmitException
815 {
816
817 SubmitContext submitContext = new WsdlTestRunContext( getModelItem() );
818 if( !amfRequestTestStep.initAmfRequest( submitContext ) )
819 {
820 throw new SubmitException( "AMF request is not initialised properly !" );
821 }
822
823 return amfRequestTestStep.getAMFRequest().submit( submitContext, true );
824 }
825
826 protected final class InputAreaFocusListener implements FocusListener
827 {
828 public InputAreaFocusListener( JComponent editor )
829 {
830 }
831
832 public void focusGained( FocusEvent e )
833 {
834 responseHasFocus = false;
835
836
837 if( !splitButton.isEnabled() )
838 {
839 requestTabs.setSelectedIndex( 0 );
840 return;
841 }
842
843
844
845
846
847
848
849
850
851
852 int pos = requestSplitPane.getDividerLocation();
853 if( pos >= 600 )
854 return;
855 if( requestSplitPane.getMaximumDividerLocation() > 700 )
856 requestSplitPane.setDividerLocation( 600 );
857 else
858 requestSplitPane.setDividerLocation( 0.8 );
859 }
860
861 public void focusLost( FocusEvent e )
862 {
863 }
864 }
865
866 protected final class ResultAreaFocusListener implements FocusListener
867 {
868 @SuppressWarnings( "unused" )
869 private final ModelItemXmlEditor<?, ?> responseEditor;
870
871 public ResultAreaFocusListener( ModelItemXmlEditor<?, ?> editor )
872 {
873 this.responseEditor = editor;
874 }
875
876 public void focusGained( FocusEvent e )
877 {
878 responseHasFocus = true;
879
880
881 if( !splitButton.isEnabled() )
882 {
883 requestTabs.setSelectedIndex( 1 );
884 return;
885 }
886
887 if( getModelItem().getSettings().getBoolean( UISettings.NO_RESIZE_REQUEST_EDITOR ) )
888 return;
889
890
891 if( requestSplitPane.getUI() instanceof SoapUISplitPaneUI
892 && ( ( SoapUISplitPaneUI )requestSplitPane.getUI() ).hasBeenDragged()
893 || amfRequestTestStep.getAMFRequest().getResponse() == null )
894 return;
895
896 int pos = requestSplitPane.getDividerLocation();
897 int maximumDividerLocation = requestSplitPane.getMaximumDividerLocation();
898 if( pos + 600 < maximumDividerLocation )
899 return;
900
901 if( maximumDividerLocation > 700 )
902 requestSplitPane.setDividerLocation( maximumDividerLocation - 600 );
903 else
904 requestSplitPane.setDividerLocation( 0.2 );
905 }
906
907 public void focusLost( FocusEvent e )
908 {
909 }
910 }
911
912 private final class ChangeToTabsAction extends AbstractAction
913 {
914 public ChangeToTabsAction()
915 {
916 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/toggle_tabs.gif" ) );
917 putValue( Action.SHORT_DESCRIPTION, "Toggles to tab-based layout" );
918 }
919
920 public void actionPerformed( ActionEvent e )
921 {
922 if( splitButton.isEnabled() )
923 {
924 splitButton.setEnabled( false );
925 removeContent( requestSplitPane );
926 setContent( requestTabPanel );
927 requestTabs.addTab( "Request", requestEditor );
928
929 if( responseEditor != null )
930 requestTabs.addTab( "Response", responseEditor );
931
932 if( responseHasFocus )
933 {
934 requestTabs.setSelectedIndex( 1 );
935 requestEditor.requestFocus();
936 }
937 requestTabs.repaint();
938 }
939 else
940 {
941 int selectedIndex = requestTabs.getSelectedIndex();
942
943 splitButton.setEnabled( true );
944 removeContent( requestTabPanel );
945 setContent( requestSplitPane );
946 requestSplitPane.setTopComponent( requestEditor );
947 if( responseEditor != null )
948 requestSplitPane.setBottomComponent( responseEditor );
949 requestSplitPane.setDividerLocation( 0.5 );
950
951 if( selectedIndex == 0 || responseEditor == null )
952 requestEditor.requestFocus();
953 else
954 responseEditor.requestFocus();
955 requestSplitPane.repaint();
956 }
957
958 revalidate();
959 }
960 }
961
962 public void setContent( JComponent content )
963 {
964 inspectorPanel.setContentComponent( content );
965 }
966
967 public void removeContent( JComponent content )
968 {
969 inspectorPanel.setContentComponent( null );
970 }
971
972 private class CancelAction extends AbstractAction
973 {
974 public CancelAction()
975 {
976 super();
977 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/cancel_request.gif" ) );
978 putValue( Action.SHORT_DESCRIPTION, "Aborts ongoing request" );
979 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt X" ) );
980 }
981
982 public void actionPerformed( ActionEvent e )
983 {
984 onCancel();
985 }
986 }
987
988 protected void onCancel()
989 {
990 if( submit == null )
991 return;
992
993 cancelButton.setEnabled( false );
994 submit.cancel();
995 setEnabled( true );
996 submit = null;
997 }
998
999 public void setEnabled( boolean enabled )
1000 {
1001 if( responseEditor != null )
1002 responseEditor.setEnabled( enabled );
1003
1004 submitButton.setEnabled( enabled );
1005 addAssertionButton.setEnabled( enabled );
1006 propertiesTableComponent.setEnabled( enabled );
1007 groovyEditor.setEnabled( enabled );
1008 endpointField.setEnabled( enabled );
1009 amfCallField.setEnabled( enabled );
1010
1011 statusBar.setIndeterminate( !enabled );
1012 }
1013
1014 public void afterSubmit( Submit submit, SubmitContext context )
1015 {
1016 if( submit.getRequest() != amfRequestTestStep.getAMFRequest() )
1017 return;
1018
1019 Status status = submit.getStatus();
1020 AMFResponse response = ( AMFResponse )submit.getResponse();
1021 if( status == Status.FINISHED )
1022 {
1023 amfRequestTestStep.setResponse( response, context );
1024 }
1025
1026 cancelButton.setEnabled( false );
1027 setEnabled( true );
1028
1029 String message = null;
1030 String infoMessage = null;
1031 String requestName = amfRequestTestStep.getName();
1032
1033 if( status == Status.CANCELED )
1034 {
1035 message = "CANCELED";
1036 infoMessage = "[" + requestName + "] - CANCELED";
1037 }
1038 else
1039 {
1040 if( status == Status.ERROR || response == null )
1041 {
1042 message = "Error getting response; " + submit.getError();
1043 infoMessage = "Error getting response for [" + requestName + "]; " + submit.getError();
1044 }
1045 else
1046 {
1047 message = "response time: " + response.getTimeTaken() + "ms (" + response.getContentLength() + " bytes)";
1048 infoMessage = "Got response for [" + requestName + "] in " + response.getTimeTaken() + "ms ("
1049 + response.getContentLength() + " bytes)";
1050
1051 if( !splitButton.isEnabled() )
1052 requestTabs.setSelectedIndex( 1 );
1053
1054 responseEditor.requestFocus();
1055 }
1056 }
1057
1058 logMessages( message, infoMessage );
1059
1060 if( getModelItem().getSettings().getBoolean( UISettings.AUTO_VALIDATE_RESPONSE ) )
1061 responseEditor.getSourceEditor().validate();
1062
1063 AMFRequestTestStepDesktopPanel.this.submit = null;
1064
1065 updateStatusIcon();
1066 }
1067
1068 protected void logMessages( String message, String infoMessage )
1069 {
1070 log.info( infoMessage );
1071 statusBar.setInfo( message );
1072 }
1073
1074 public boolean beforeSubmit( Submit submit, SubmitContext context )
1075 {
1076 if( submit.getRequest() != amfRequestTestStep.getAMFRequest() )
1077 return true;
1078
1079 setEnabled( false );
1080 cancelButton.setEnabled( AMFRequestTestStepDesktopPanel.this.submit != null );
1081 return true;
1082 }
1083
1084 public void propertyChange( PropertyChangeEvent evt )
1085 {
1086 super.propertyChange( evt );
1087 if( evt.getPropertyName().equals( "script" ) && !updating )
1088 {
1089 updating = true;
1090 groovyEditor.getEditArea().setText( ( String )evt.getNewValue() );
1091 updating = false;
1092 }
1093 if( evt.getPropertyName().equals( AMFRequestTestStep.STATUS_PROPERTY ) )
1094 updateStatusIcon();
1095 }
1096
1097 private final class InternalAssertionsListener implements AssertionsListener
1098 {
1099 public void assertionAdded( TestAssertion assertion )
1100 {
1101 assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
1102 }
1103
1104 public void assertionRemoved( TestAssertion assertion )
1105 {
1106 assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
1107 }
1108
1109 public void assertionMoved( TestAssertion assertion, int ix, int offset )
1110 {
1111 assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
1112 }
1113 }
1114
1115 private void updateStatusIcon()
1116 {
1117 AssertionStatus status = amfRequestTestStep.getAssertionStatus();
1118 switch( status )
1119 {
1120 case FAILED :
1121 {
1122 assertionInspector.setIcon( UISupport.createImageIcon( "/failed_assertion.gif" ) );
1123 inspectorPanel.activate( assertionInspector );
1124 break;
1125 }
1126 case UNKNOWN :
1127 {
1128 assertionInspector.setIcon( UISupport.createImageIcon( "/unknown_assertion.gif" ) );
1129 break;
1130 }
1131 case VALID :
1132 {
1133 assertionInspector.setIcon( UISupport.createImageIcon( "/valid_assertion.gif" ) );
1134 inspectorPanel.deactivate();
1135 break;
1136 }
1137 }
1138 }
1139
1140 }