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