1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.monitor;
14
15 import com.eviware.soapui.SoapUI;
16 import com.eviware.soapui.impl.support.AbstractInterface;
17 import com.eviware.soapui.impl.wsdl.WsdlInterface;
18 import com.eviware.soapui.impl.wsdl.WsdlProject;
19 import com.eviware.soapui.impl.wsdl.WsdlRequest;
20 import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
21 import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation;
22 import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
23 import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
24 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
25 import com.eviware.soapui.impl.wsdl.support.MessageExchangeModelItem;
26 import com.eviware.soapui.impl.wsdl.support.MessageExchangeRequestMessageEditor;
27 import com.eviware.soapui.impl.wsdl.support.MessageExchangeResponseMessageEditor;
28 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
29 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequest;
30 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
31 import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestRequestStepFactory;
32 import com.eviware.soapui.model.iface.Attachment;
33 import com.eviware.soapui.model.iface.Interface;
34 import com.eviware.soapui.model.settings.Settings;
35 import com.eviware.soapui.model.support.ModelSupport;
36 import com.eviware.soapui.model.testsuite.TestSuite;
37 import com.eviware.soapui.settings.ProxySettings;
38 import com.eviware.soapui.support.StringUtils;
39 import com.eviware.soapui.support.UISupport;
40 import com.eviware.soapui.support.components.JComponentInspector;
41 import com.eviware.soapui.support.components.JInspectorPanel;
42 import com.eviware.soapui.support.components.JInspectorPanelFactory;
43 import com.eviware.soapui.support.components.JXToolBar;
44 import com.eviware.soapui.support.types.StringList;
45 import com.eviware.x.form.XFormDialog;
46 import com.eviware.x.form.XFormField;
47 import com.eviware.x.form.XFormFieldListener;
48 import com.eviware.x.form.support.ADialogBuilder;
49 import com.eviware.x.form.support.AField;
50 import com.eviware.x.form.support.AField.AFieldType;
51 import com.eviware.x.form.support.AForm;
52 import com.jgoodies.forms.builder.ButtonBarBuilder;
53 import org.jdesktop.swingx.JXTable;
54 import org.jdesktop.swingx.decorator.Filter;
55 import org.jdesktop.swingx.decorator.FilterPipeline;
56 import org.jdesktop.swingx.decorator.PatternFilter;
57
58 import javax.swing.*;
59 import javax.swing.event.ListSelectionEvent;
60 import javax.swing.event.ListSelectionListener;
61 import javax.swing.table.AbstractTableModel;
62 import java.awt.*;
63 import java.awt.event.ActionEvent;
64 import java.awt.event.ActionListener;
65 import java.awt.event.ItemEvent;
66 import java.awt.event.ItemListener;
67 import java.net.MalformedURLException;
68 import java.net.URL;
69 import java.text.DateFormat;
70 import java.text.SimpleDateFormat;
71 import java.util.*;
72 import java.util.List;
73
74 /***
75 * A SOAP Monitor..
76 */
77
78 @SuppressWarnings( "serial" )
79 public class SoapMonitor extends JPanel
80 {
81 private static final String ALL_FILTER_OPTION = "- all -";
82 private JProgressBar progressBar;
83 private JButton stopButton = null;
84
85 private JXTable logTable = null;
86 private MonitorLogTableModel tableModel = null;
87
88 private String httpProxyHost = null;
89 private int httpProxyPort = 80;
90
91 private JButton startButton;
92 private final WsdlProject project;
93 private MessageExchangeRequestMessageEditor requestViewer;
94 private MessageExchangeResponseMessageEditor responseViewer;
95 private Set<SoapMonitorListener> listeners = new HashSet<SoapMonitorListener>();
96 private MessageExchangeModelItem requestModelItem;
97 private JButton optionsButton;
98 private int listenPort;
99 private String targetEndpoint;
100 private JButton clearButton;
101 private int maxRows;
102 private JButton addToTestCaseButton;
103 private JButton createRequestButton;
104 private JButton addToMockServiceButton;
105 private Stack<WsdlMonitorMessageExchange> messageExchangeStack = new Stack<WsdlMonitorMessageExchange>();
106 private StackProcessor stackProcessor = new StackProcessor();
107 private PatternFilter operationFilter;
108 private PatternFilter interfaceFilter;
109 private PatternFilter targetHostFilter;
110 private JLabel infoLabel;
111 private PatternFilter requestHostFilter;
112 private JComboBox requestHostFilterCombo;
113 private JComboBox targetHostFilterCombo;
114 private JComboBox interfaceFilterCombo;
115 private JComboBox operationFilterCombo;
116 private DefaultComboBoxModel operationFilterModel;
117 private DefaultComboBoxModel requestFilterModel;
118 private DefaultComboBoxModel targetHostFilterModel;
119 private JLabel rowCountLabel = new JLabel();
120 private Map<AbstractInterface<?>, String> addedEndpoints;
121 private JXToolBar toolbar;
122 private String incomingRequestWss;
123 private String incomingResponseWss;
124 private boolean setAsProxy;
125 private XFormDialog optionsDialog;
126 private SoapMonitorEngine monitorEngine;
127 private String oldProxyHost;
128 private String oldProxyPort;
129 private String sslEndpoint;
130
131 public SoapMonitor(
132 WsdlProject project, int listenPort,
133 String incomingRequestWss, String incomingResponseWss, JXToolBar mainToolbar, boolean setAsProxy, String sslEndpoint
134 )
135 {
136 super( new BorderLayout() );
137 this.project = project;
138 this.listenPort = listenPort;
139 this.incomingRequestWss = incomingRequestWss;
140 this.incomingResponseWss = incomingResponseWss;
141 this.setAsProxy = setAsProxy;
142 this.maxRows = 100;
143 this.sslEndpoint = sslEndpoint;
144
145
146
147 this.setLayout( new BorderLayout() );
148
149 add( buildToolbars( mainToolbar ), BorderLayout.NORTH );
150 add( buildContent(), BorderLayout.CENTER );
151
152 start();
153 }
154
155 public SoapMonitor(
156 WsdlProject project, int sourcePort, String incomingRequestWss, String incomingResponseWss,
157 JXToolBar toolbar, boolean setAsProxy
158 )
159 {
160 this( project, sourcePort, incomingRequestWss, incomingResponseWss, toolbar, setAsProxy, null );
161 }
162
163 private JComponent buildContent()
164 {
165 JInspectorPanel inspectorPanel = JInspectorPanelFactory.build( buildLog() );
166
167 JComponentInspector<JComponent> viewInspector = new JComponentInspector<JComponent>( buildViewer(), "Message Content",
168 "Shows message content", true );
169 inspectorPanel.addInspector( viewInspector );
170
171 return inspectorPanel.getComponent();
172 }
173
174 private JComponent buildLog()
175 {
176 tableModel = new MonitorLogTableModel();
177 logTable = new JXTable( 1, 2 );
178 logTable.setColumnControlVisible( true );
179 logTable.setModel( tableModel );
180 logTable.setHorizontalScrollEnabled( true );
181 logTable.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
182
183 operationFilter = new PatternFilter( ".*", 0, 4 );
184 operationFilter.setAcceptNull( true );
185 interfaceFilter = new PatternFilter( ".*", 0, 3 );
186 interfaceFilter.setAcceptNull( true );
187 targetHostFilter = new PatternFilter( ".*", 0, 2 );
188 targetHostFilter.setAcceptNull( true );
189 requestHostFilter = new PatternFilter( ".*", 0, 1 );
190 requestHostFilter.setAcceptNull( true );
191
192 Filter[] filters = new Filter[]{requestHostFilter, targetHostFilter, interfaceFilter, operationFilter};
193
194 FilterPipeline pipeline = new FilterPipeline( filters );
195 logTable.setFilters( pipeline );
196
197 ListSelectionModel sel = logTable.getSelectionModel();
198 sel.addListSelectionListener( new ListSelectionListener()
199 {
200 public void valueChanged( ListSelectionEvent event )
201 {
202 int row = logTable.getSelectedRow();
203 if( row == -1 )
204 {
205
206
207 requestModelItem.setMessageExchange( null );
208 }
209 else
210 {
211 WsdlMonitorMessageExchange exchange = tableModel.getMessageExchangeAt( row );
212 requestModelItem.setMessageExchange( exchange );
213
214
215
216 }
217
218 addToMockServiceButton.setEnabled( row != -1 );
219 addToTestCaseButton.setEnabled( row != -1 );
220 createRequestButton.setEnabled( row != -1 );
221 }
222 } );
223
224 JPanel tablePane = new JPanel();
225 tablePane.setLayout( new BorderLayout() );
226
227 toolbar.addGlue();
228
229 tablePane.add( buildFilterBar(), BorderLayout.NORTH );
230 tablePane.add( new JScrollPane( logTable ), BorderLayout.CENTER );
231
232 return tablePane;
233 }
234
235 private JPanel buildFilterBar()
236 {
237 requestFilterModel = new DefaultComboBoxModel( new String[]{ALL_FILTER_OPTION} );
238 targetHostFilterModel = new DefaultComboBoxModel( new String[]{ALL_FILTER_OPTION} );
239 Dimension comboBoxSize = new Dimension( 90, 18 );
240 requestHostFilterCombo = UISupport.setFixedSize( new JComboBox( requestFilterModel ), comboBoxSize );
241
242
243
244
245 ButtonBarBuilder toolbar = new ButtonBarBuilder();
246
247 toolbar.addFixed( new JLabel( "Request Host" ) );
248 toolbar.addRelatedGap();
249 toolbar.addFixed( requestHostFilterCombo );
250 toolbar.addUnrelatedGap();
251
252 requestHostFilterCombo.addItemListener( new ItemListener()
253 {
254 public void itemStateChanged( ItemEvent e )
255 {
256 int ix = requestHostFilterCombo.getSelectedIndex();
257 if( ix == -1 )
258 return;
259
260 requestHostFilter.setAcceptNull( ix == 0 );
261
262 if( ix == 0 )
263 requestHostFilter.setPattern( ".*", 0 );
264 else
265 requestHostFilter.setPattern( requestHostFilterCombo.getSelectedItem().toString(), 0 );
266
267 updateRowCountLabel();
268 }
269 } );
270
271 toolbar.addFixed( new JLabel( "Target Host" ) );
272 toolbar.addRelatedGap();
273 targetHostFilterCombo = UISupport.setFixedSize( new JComboBox( targetHostFilterModel ), comboBoxSize );
274 toolbar.addFixed( targetHostFilterCombo );
275 toolbar.addUnrelatedGap();
276
277 targetHostFilterCombo.addItemListener( new ItemListener()
278 {
279 public void itemStateChanged( ItemEvent e )
280 {
281 int ix = targetHostFilterCombo.getSelectedIndex();
282 if( ix == -1 )
283 return;
284
285 targetHostFilter.setAcceptNull( ix == 0 );
286
287 if( ix == 0 )
288 targetHostFilter.setPattern( ".*", 0 );
289 else
290 targetHostFilter.setPattern( targetHostFilterCombo.getSelectedItem().toString(), 0 );
291
292 updateRowCountLabel();
293 }
294 } );
295
296 String[] interfaceNames = ModelSupport
297 .getNames( new String[]{ALL_FILTER_OPTION},
298 ModelSupport.getChildren( getProject(), WsdlInterface.class ) );
299
300 toolbar.addFixed( new JLabel( "Interface" ) );
301 toolbar.addRelatedGap();
302 interfaceFilterCombo = UISupport.setFixedSize( new JComboBox( interfaceNames ), comboBoxSize );
303 toolbar.addFixed( interfaceFilterCombo );
304 toolbar.addUnrelatedGap();
305
306 operationFilterModel = new DefaultComboBoxModel( new String[]{ALL_FILTER_OPTION} );
307 interfaceFilterCombo.addItemListener( new ItemListener()
308 {
309 public void itemStateChanged( ItemEvent e )
310 {
311 String item = (String) interfaceFilterCombo.getSelectedItem();
312 operationFilterModel.removeAllElements();
313
314 if( item == null || getProject().getInterfaceByName( item ) == null )
315 {
316 operationFilterModel.addElement( ALL_FILTER_OPTION );
317 interfaceFilter.setPattern( ".*", 0 );
318 }
319 else if( getProject().getInterfaceByName( item ) != null )
320 {
321 WsdlInterface iface = (WsdlInterface) getProject().getInterfaceByName( item );
322 String[] operationNames = ModelSupport.getNames( new String[]{ALL_FILTER_OPTION}, iface
323 .getOperationList() );
324 for( String s : operationNames )
325 operationFilterModel.addElement( s );
326
327 interfaceFilter.setPattern( iface.getName(), 0 );
328 }
329 }
330 } );
331
332 toolbar.addFixed( new JLabel( "Operation" ) );
333 toolbar.addRelatedGap();
334 operationFilterCombo = UISupport.setFixedSize( new JComboBox( operationFilterModel ), comboBoxSize );
335 toolbar.addFixed( operationFilterCombo );
336
337 operationFilterCombo.addItemListener( new ItemListener()
338 {
339 public void itemStateChanged( ItemEvent e )
340 {
341 int ix = operationFilterCombo.getSelectedIndex();
342 if( ix == -1 )
343 {
344 operationFilter.setPattern( ".*", 0 );
345 updateRowCountLabel();
346 return;
347 }
348
349 operationFilter.setAcceptNull( ix == 0 );
350
351 if( ix == 0 )
352 operationFilter.setPattern( ".*", 0 );
353 else
354 operationFilter.setPattern( operationFilterCombo.getSelectedItem().toString(), 0 );
355
356 updateRowCountLabel();
357 }
358 } );
359
360 toolbar.setBorder( BorderFactory.createEmptyBorder( 3, 2, 3, 0 ) );
361 return toolbar.getPanel();
362 }
363
364 protected void updateRowCountLabel()
365 {
366 rowCountLabel.setText( logTable.getRowCount() + "/" + tableModel.getRowCount() + " entries" );
367 }
368
369 private JComponent buildViewer()
370 {
371 requestModelItem = new MessageExchangeModelItem( "monitor message exchange", null )
372 {
373
374 @Override
375 public boolean hasRawData()
376 {
377 return true;
378 }
379 };
380
381 requestViewer = new MessageExchangeRequestMessageEditor( requestModelItem );
382 responseViewer = new MessageExchangeResponseMessageEditor( requestModelItem );
383
384 return UISupport.createHorizontalSplit( requestViewer, responseViewer );
385 }
386
387 private JComponent buildToolbars( JXToolBar mainToolbar )
388 {
389 toolbar = UISupport.createSmallToolbar();
390 mainToolbar.addFixed( startButton = UISupport.createToolbarButton( UISupport.createImageIcon( "/run_testcase.gif" ) ) );
391 mainToolbar.addFixed( stopButton = UISupport.createToolbarButton( UISupport.createImageIcon( "/stop_testcase.gif" ) ) );
392 mainToolbar.addFixed( optionsButton = UISupport.createToolbarButton( new SoapMonitorOptionsAction() ) );
393
394 toolbar.addFixed( createRequestButton = UISupport.createToolbarButton( UISupport.createImageIcon( "/request.gif" ) ) );
395 toolbar.addFixed( addToTestCaseButton = UISupport.createToolbarButton( UISupport.createImageIcon( "/testCase.gif" ) ) );
396 toolbar.addFixed( addToMockServiceButton = UISupport.createToolbarButton( UISupport.createImageIcon( "/mockService.gif" ) ) );
397 toolbar.addFixed( clearButton = UISupport.createToolbarButton( UISupport.createImageIcon( "/clear_loadtest.gif" ) ) );
398
399 startButton.setToolTipText( "Starts the SOAP Monitor as configured" );
400 stopButton.setToolTipText( "Stops the SOAP Monitor" );
401 optionsButton.setToolTipText( "Sets Monitor Options" );
402 clearButton.setToolTipText( "Clear all/selected messages from the log" );
403 createRequestButton.setToolTipText( "Creates requests from selected messages" );
404 addToTestCaseButton.setToolTipText( "Adds selected requests to a TestCase" );
405 addToMockServiceButton.setToolTipText( "Adds selected reponses to a MockService" );
406
407 createRequestButton.setEnabled( false );
408 addToMockServiceButton.setEnabled( false );
409 addToTestCaseButton.setEnabled( false );
410
411 startButton.addActionListener( new ActionListener()
412 {
413 public void actionPerformed( ActionEvent e )
414 {
415 start();
416 }
417 } );
418
419 stopButton.addActionListener( new ActionListener()
420 {
421 public void actionPerformed( ActionEvent e )
422 {
423 stop();
424 }
425 } );
426
427 clearButton.addActionListener( new ClearAction() );
428 createRequestButton.addActionListener( new CreateRequestsAction() );
429 addToTestCaseButton.addActionListener( new AddToTestCaseAction() );
430 addToMockServiceButton.addActionListener( new AddToMockServiceAction() );
431
432 mainToolbar.addGlue();
433
434 infoLabel = new JLabel();
435 infoLabel.setPreferredSize( new Dimension( 150, 20 ) );
436 infoLabel.setOpaque( false );
437 mainToolbar.addFixed( infoLabel );
438
439 progressBar = new JProgressBar();
440
441 JPanel progressBarPanel = UISupport.createProgressBarPanel( progressBar, 2, false );
442 progressBarPanel.setPreferredSize( new Dimension( 60, 20 ) );
443
444 mainToolbar.addFixed( progressBarPanel );
445 return toolbar;
446 }
447
448 /***
449 * Method start
450 */
451 public void start()
452 {
453 int localPort = getLocalPort();
454
455
456 monitorEngine = new SoapMonitorEngineImpl();
457 ( (SoapMonitorEngineImpl) monitorEngine ).setSslEndpoint( sslEndpoint );
458 monitorEngine.start( this, localPort );
459
460 if( monitorEngine.isRunning() )
461 {
462 stopButton.setEnabled( true );
463 startButton.setEnabled( false );
464 optionsButton.setEnabled( false );
465 infoLabel.setText( ( monitorEngine.isProxy() ? "Http Proxy " : "SSL Tunnel " ) + "on port " + localPort );
466 progressBar.setIndeterminate( true );
467
468 if( setAsProxy )
469 {
470 oldProxyHost = SoapUI.getSettings().getString( ProxySettings.HOST, "" );
471 oldProxyPort = SoapUI.getSettings().getString( ProxySettings.PORT, "" );
472
473 SoapUI.getSettings().setString( ProxySettings.HOST, "127.0.0.1" );
474 SoapUI.getSettings().setString( ProxySettings.PORT, String.valueOf( localPort ) );
475 }
476
477 SoapUI.log.info( "Started SOAP Monitor on local port " + localPort );
478 }
479 else
480 {
481 stopButton.setEnabled( false );
482 startButton.setEnabled( true );
483 optionsButton.setEnabled( true );
484 infoLabel.setText( "Stoped" );
485 progressBar.setIndeterminate( false );
486
487 SoapUI.log.info( "Could not start SOAP Monitor on local port " + localPort );
488 }
489 }
490
491 /***
492 * Method close
493 */
494 public void close()
495 {
496 stop();
497 }
498
499 /***
500 * Method stop
501 */
502 public void stop()
503 {
504 monitorEngine.stop();
505 if( addedEndpoints != null )
506 {
507 for( Interface iface : addedEndpoints.keySet() )
508 iface.removeEndpoint( addedEndpoints.get( iface ) );
509
510 addedEndpoints.clear();
511 }
512
513 stopButton.setEnabled( false );
514 startButton.setEnabled( true );
515 optionsButton.setEnabled( true );
516 progressBar.setIndeterminate( false );
517 infoLabel.setText( "Stopped" );
518
519 if( setAsProxy )
520 {
521 SoapUI.getSettings().setString( ProxySettings.HOST, oldProxyHost );
522 SoapUI.getSettings().setString( ProxySettings.PORT, oldProxyPort );
523 }
524 }
525
526 @AForm( description = "Set options for adding selected requests to a MockService", name = "Add To MockService" )
527 private final class AddToMockServiceAction implements ActionListener
528 {
529 private static final String CREATE_NEW_OPTION = "<Create New>";
530 private XFormDialog dialog;
531
532 @AField( name = "Target MockService", description = "The target TestSuite", type = AFieldType.ENUMERATION )
533 public final static String MOCKSERVICE = "Target MockService";
534
535 @AField( name = "Open Editor", description = "Open the created MockService", type = AFieldType.BOOLEAN )
536 public final static String OPENEDITOR = "Open Editor";
537
538 public void actionPerformed( ActionEvent e )
539 {
540 int[] rows = logTable.getSelectedRows();
541 if( rows.length == 0 )
542 return;
543
544 if( dialog == null )
545 {
546 dialog = ADialogBuilder.buildDialog( this.getClass() );
547 }
548
549 String[] testSuiteNames = ModelSupport.getNames( new String[]{CREATE_NEW_OPTION}, getProject()
550 .getMockServiceList() );
551 dialog.setOptions( MOCKSERVICE, testSuiteNames );
552
553 if( dialog.show() )
554 {
555 String targetMockServiceName = dialog.getValue( MOCKSERVICE );
556
557 WsdlMockService mockService = getProject().getMockServiceByName( targetMockServiceName );
558 if( mockService == null )
559 {
560 targetMockServiceName = ModelSupport.promptForUniqueName( "MockService", getProject(), "" );
561 if( targetMockServiceName == null )
562 return;
563
564 mockService = getProject().addNewMockService( targetMockServiceName );
565 mockService.setIncomingWss( incomingResponseWss );
566 }
567
568 int cnt = 0;
569 for( int row : rows )
570 {
571 WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt( row );
572 if( me.getOperation() == null )
573 continue;
574
575 WsdlMockOperation mockOperation = mockService.getMockOperation( me.getOperation() );
576 if( mockOperation == null )
577 mockOperation = mockService.addNewMockOperation( me.getOperation() );
578
579 WsdlMockResponse mockResponse = mockOperation.addNewMockResponse( "Monitor Response " + ( ++cnt ), false );
580 mockResponse.setResponseContent( me.getResponseContent() );
581
582 Attachment[] requestAttachments = me.getResponseAttachments();
583 if( requestAttachments != null )
584 {
585 for( Attachment attachment : requestAttachments )
586 {
587 mockResponse.addAttachment( attachment );
588 }
589 }
590 }
591
592 if( cnt == 0 )
593 {
594 UISupport.showInfoMessage( "No response messages found" );
595 }
596 else
597 {
598 UISupport.showInfoMessage( "Added " + cnt + " MockResponses to MockService" );
599
600 if( dialog.getBooleanValue( OPENEDITOR ) )
601 UISupport.selectAndShow( mockService );
602 }
603 }
604 }
605 }
606
607 @AForm( description = "Set options for adding selected requests to a TestCase", name = "Add To TestCase" )
608 private final class AddToTestCaseAction implements ActionListener
609 {
610 private static final String CREATE_NEW_OPTION = "<Create New>";
611 private XFormDialog dialog;
612
613 @AField( name = "Target TestCase", description = "The target TestCase for the requests", type = AFieldType.ENUMERATION )
614 public final static String TESTCASE = "Target TestCase";
615
616 @AField( name = "Target TestSuite", description = "The target TestSuite", type = AFieldType.ENUMERATION )
617 public final static String TESTSUITE = "Target TestSuite";
618
619 @AField( name = "Open Editor", description = "Open the created TestCase", type = AFieldType.BOOLEAN )
620 public final static String OPENEDITOR = "Open Editor";
621
622 public void actionPerformed( ActionEvent e )
623 {
624 int[] rows = logTable.getSelectedRows();
625 if( rows.length == 0 )
626 return;
627
628 if( dialog == null )
629 {
630 dialog = ADialogBuilder.buildDialog( this.getClass() );
631 dialog.getFormField( TESTSUITE ).addFormFieldListener( new XFormFieldListener()
632 {
633 public void valueChanged( XFormField sourceField, String newValue, String oldValue )
634 {
635 if( newValue.equals( CREATE_NEW_OPTION ) )
636 {
637 dialog.setOptions( TESTCASE, new String[]{CREATE_NEW_OPTION} );
638 }
639 else
640 {
641 TestSuite testSuite = getProject().getTestSuiteByName( newValue );
642 dialog.setOptions( TESTCASE, testSuite == null ? new String[]{CREATE_NEW_OPTION} : ModelSupport
643 .getNames( testSuite.getTestCaseList(), new String[]{CREATE_NEW_OPTION} ) );
644 }
645 }
646 } );
647 }
648
649 String[] testSuiteNames = ModelSupport.getNames( new String[]{CREATE_NEW_OPTION}, getProject()
650 .getTestSuiteList() );
651 dialog.setOptions( TESTSUITE, testSuiteNames );
652 dialog.setOptions( TESTCASE, new String[]{CREATE_NEW_OPTION} );
653
654 if( dialog.show() )
655 {
656 String targetTestSuiteName = dialog.getValue( TESTSUITE );
657 String targetTestCaseName = dialog.getValue( TESTCASE );
658
659 WsdlTestSuite testSuite = getProject().getTestSuiteByName( targetTestSuiteName );
660 if( testSuite == null )
661 {
662 targetTestSuiteName = ModelSupport.promptForUniqueName( "TestSuite", getProject(), "" );
663 if( targetTestSuiteName == null )
664 return;
665
666 testSuite = getProject().addNewTestSuite( targetTestSuiteName );
667 }
668
669 WsdlTestCase testCase = testSuite.getTestCaseByName( targetTestCaseName );
670 if( testCase == null )
671 {
672 targetTestCaseName = ModelSupport.promptForUniqueName( "TestCase", testSuite, "" );
673 if( targetTestCaseName == null )
674 return;
675
676 testCase = testSuite.addNewTestCase( targetTestCaseName );
677 }
678
679 for( int row : rows )
680 {
681 WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt( row );
682 if( me.getOperation() == null )
683 continue;
684
685 WsdlTestRequestStep test = (WsdlTestRequestStep) testCase.insertTestStep( WsdlTestRequestStepFactory
686 .createConfig( me.getOperation(), "Monitor Request " + ( row + 1 ) ), -1 );
687
688 WsdlTestRequest request = test.getTestRequest();
689 request.setRequestContent( me.getRequestContent() );
690 request.setEndpoint( me.getTargetUrl().toString() );
691 request.setIncomingWss( incomingRequestWss );
692
693 Attachment[] requestAttachments = me.getRequestAttachments();
694 if( requestAttachments != null )
695 {
696 for( Attachment attachment : requestAttachments )
697 {
698 request.importAttachment( attachment );
699 }
700 }
701 }
702
703 if( dialog.getBooleanValue( OPENEDITOR ) )
704 UISupport.selectAndShow( testCase );
705 }
706 }
707 }
708
709 private final class CreateRequestsAction implements ActionListener
710 {
711 public void actionPerformed( ActionEvent e )
712 {
713 int[] rows = logTable.getSelectedRows();
714 if( rows.length == 0 )
715 return;
716
717 if( UISupport.confirm( "Create " + rows.length + " requests", "Create Request" ) )
718 {
719 for( int row : rows )
720 {
721 WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt( row );
722 if( me.getOperation() == null )
723 continue;
724
725 WsdlRequest request = me.getOperation().addNewRequest( "Monitor Request " + ( row + 1 ) );
726
727 request.setRequestContent( me.getRequestContent() );
728 request.setEndpoint( me.getTargetUrl().toString() );
729
730 Attachment[] requestAttachments = me.getRequestAttachments();
731 if( requestAttachments != null )
732 {
733 for( Attachment attachment : requestAttachments )
734 {
735 request.importAttachment( attachment );
736 }
737 }
738 }
739 }
740 }
741 }
742
743 private final class ClearAction implements ActionListener
744 {
745 public void actionPerformed( ActionEvent e )
746 {
747 if( logTable.getRowCount() == 0 )
748 return;
749
750 int[] rows = logTable.getSelectedRows();
751
752 if( rows.length == 0 )
753 {
754 if( UISupport.confirm( "Clear monitor log?", "Clear Log" ) )
755 tableModel.clear();
756 }
757 else if( UISupport.confirm( "Clear " + rows.length + " rows from monitor log?", "Clear Log" ) )
758 {
759 tableModel.clearRows( rows );
760 }
761 }
762 }
763
764 public class MonitorLogTableModel extends AbstractTableModel
765 {
766 private List<WsdlMonitorMessageExchange> exchanges = new LinkedList<WsdlMonitorMessageExchange>();
767 private DateFormat sdf;
768
769 public MonitorLogTableModel()
770 {
771 sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
772 }
773
774 public synchronized void clear()
775 {
776 int sz = exchanges.size();
777 while( exchanges.size() > 0 )
778 {
779 WsdlMonitorMessageExchange removed = exchanges.remove( 0 );
780 removed.discard();
781 }
782
783 fireTableRowsDeleted( 0, sz );
784
785 while( requestFilterModel.getSize() > 1 )
786 requestFilterModel.removeElementAt( 1 );
787
788 while( targetHostFilterModel.getSize() > 1 )
789 targetHostFilterModel.removeElementAt( 1 );
790
791 updateRowCountLabel();
792 }
793
794 public synchronized void clearRows( int[] indices )
795 {
796 for( int c = indices.length; c > 0; c-- )
797 {
798 int index = indices[c - 1];
799 WsdlMonitorMessageExchange removed = exchanges.remove( logTable.convertRowIndexToModel( index ) );
800 removed.discard();
801 fireTableRowsDeleted( index, index );
802 updateRowCountLabel();
803 }
804 }
805
806 public int getColumnCount()
807 {
808 return 8;
809 }
810
811 public WsdlMonitorMessageExchange getMessageExchangeAt( int tableRow )
812 {
813 return exchanges.get( logTable.convertRowIndexToModel( tableRow ) );
814 }
815
816 @Override
817 public String getColumnName( int column )
818 {
819 switch( column )
820 {
821 case 0:
822 return "Time";
823 case 1:
824 return "Request Host";
825 case 2:
826 return "Target Host";
827 case 3:
828 return "Interface";
829 case 4:
830 return "Operation";
831 case 5:
832 return "Time Taken";
833 case 6:
834 return "Req Sz";
835 case 7:
836 return "Resp Sz";
837 }
838
839 return null;
840 }
841
842 public int getRowCount()
843 {
844 return exchanges.size();
845 }
846
847 public Object getValueAt( int rowIndex, int columnIndex )
848 {
849 if( rowIndex < 0 || rowIndex >= exchanges.size() )
850 return null;
851
852 WsdlMonitorMessageExchange exchange = exchanges.get( rowIndex );
853 if( exchange == null )
854 return null;
855
856 switch( columnIndex )
857 {
858 case 0:
859 return sdf.format( new Date( exchange.getTimestamp() ) );
860 case 1:
861 return exchange.getRequestHost();
862 case 2:
863 return exchange.getTargetUrl().getHost();
864 case 3:
865 return exchange.getOperation() == null ? "- unknown -" : exchange.getOperation().getInterface().getName();
866 case 4:
867 return exchange.getOperation() == null ? "- unknown -" : exchange.getOperation().getName();
868 case 5:
869 return String.valueOf( exchange.getTimeTaken() );
870 case 6:
871 return String.valueOf( exchange.getRequestContentLength() );
872 case 7:
873 return String.valueOf( exchange.getResponseContentLength() );
874 }
875
876 return null;
877 }
878
879 public synchronized void addMessageExchange( WsdlMonitorMessageExchange exchange )
880 {
881 exchanges.add( exchange );
882 int size = exchanges.size();
883 fireTableRowsInserted( size - 1, size );
884
885 fitSizeToMaxRows();
886
887 String requestHost = exchange.getRequestHost();
888 if( requestFilterModel.getIndexOf( requestHost ) == -1 )
889 {
890 requestFilterModel.addElement( requestHost );
891 }
892
893 String host = exchange.getTargetUrl().getHost();
894 if( targetHostFilterModel.getIndexOf( host ) == -1 )
895 {
896 targetHostFilterModel.addElement( host );
897 }
898
899 updateRowCountLabel();
900 }
901
902 public void fitSizeToMaxRows()
903 {
904 int removeCnt = 0;
905
906 while( exchanges.size() > maxRows )
907 {
908 WsdlMonitorMessageExchange removed = exchanges.remove( 0 );
909 removed.discard();
910 removeCnt++;
911 }
912
913 if( removeCnt > 0 )
914 {
915 fireTableDataChanged();
916 updateRowCountLabel();
917 }
918 }
919 }
920
921 protected String getHttpProxyHost()
922 {
923 return httpProxyHost;
924 }
925
926 protected void setHttpProxyHost( String proxyHost )
927 {
928 httpProxyHost = proxyHost;
929 }
930
931 protected int getHttpProxyPort()
932 {
933 return httpProxyPort;
934 }
935
936 protected void setHttpProxyPort( int proxyPort )
937 {
938 httpProxyPort = proxyPort;
939 }
940
941
942
943
944
945
946 public String getTargetHost()
947 {
948 String host = targetEndpoint;
949
950 try
951 {
952 URL url = new URL( host );
953 return url.getHost();
954 }
955 catch( MalformedURLException e )
956 {
957 return host;
958 }
959 }
960
961 public String getTargetEndpoint()
962 {
963 return targetEndpoint;
964 }
965
966 public int getTargetPort()
967 {
968 try
969 {
970 URL url = new URL( targetEndpoint );
971 return url.getPort() == -1 ? 80 : url.getPort();
972 }
973 catch( MalformedURLException e )
974 {
975 return 80;
976 }
977 }
978
979 public int getLocalPort()
980 {
981 return listenPort;
982 }
983
984 public synchronized void addMessageExchange( WsdlMonitorMessageExchange messageExchange )
985 {
986 messageExchangeStack.push( messageExchange );
987
988 if( !stackProcessor.isRunning() )
989 new Thread( stackProcessor, "SoapMonitor StackProcessor for project [" + getProject().getName() + "]" )
990 .start();
991 }
992
993 private class StackProcessor implements Runnable
994 {
995 private boolean canceled;
996 private boolean running;
997
998 public void run()
999 {
1000 running = true;
1001 SoapUI.log.info( "Started stackprocessor for soapmonitor in project [" + getProject().getName() + "]" );
1002 while( !canceled && messageExchangeStack.size() > 0 )
1003 {
1004 WsdlMonitorMessageExchange messageExchange = messageExchangeStack.pop();
1005 if( messageExchange != null )
1006 {
1007 processMessage( messageExchange );
1008 }
1009
1010 try
1011 {
1012 Thread.sleep( 100 );
1013 }
1014 catch( InterruptedException e )
1015 {
1016 e.printStackTrace();
1017 }
1018 }
1019 running = false;
1020 }
1021
1022 private synchronized void processMessage( WsdlMonitorMessageExchange messageExchange )
1023 {
1024 messageExchange.prepare(
1025 project.getWssContainer().getIncomingWssByName( incomingRequestWss ),
1026 project.getWssContainer().getIncomingWssByName( incomingResponseWss ) );
1027
1028 tableModel.addMessageExchange( messageExchange );
1029 if( logTable.getSelectedRow() == logTable.getRowCount() - 2 )
1030 {
1031 logTable.setRowSelectionInterval( logTable.getRowCount() - 1, logTable.getRowCount() - 1 );
1032 }
1033
1034 fireOnMessageExchange( messageExchange );
1035 }
1036
1037 public void cancel()
1038 {
1039 canceled = true;
1040 }
1041
1042 protected boolean isCanceled()
1043 {
1044 return canceled;
1045 }
1046
1047 protected boolean isRunning()
1048 {
1049 return running;
1050 }
1051 }
1052
1053 public MonitorLogTableModel getLogModel()
1054 {
1055 return tableModel;
1056 }
1057
1058 public void addSoapMonitorListener( SoapMonitorListener listener )
1059 {
1060 listeners.add( listener );
1061 }
1062
1063 public void fireOnMessageExchange( WsdlMonitorMessageExchange messageExchange )
1064 {
1065 for( SoapMonitorListener listener : listeners.toArray( new SoapMonitorListener[listeners.size()] ) )
1066 {
1067 listener.onMessageExchange( messageExchange );
1068 }
1069 }
1070
1071 public void removeSoapMonitorListener( SoapMonitorListener listener )
1072 {
1073 listeners.remove( listener );
1074 }
1075
1076 public WsdlProject getProject()
1077 {
1078 return project;
1079 }
1080
1081 public class SoapMonitorOptionsAction extends AbstractAction
1082 {
1083
1084 public SoapMonitorOptionsAction()
1085 {
1086 putValue( SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
1087 }
1088
1089 public void actionPerformed( ActionEvent e )
1090 {
1091 if( optionsDialog == null )
1092 {
1093 optionsDialog = ADialogBuilder.buildDialog( OptionsForm.class );
1094 }
1095
1096 StringList endpoints = new StringList();
1097 endpoints.add( null );
1098
1099 for( WsdlInterface iface : ModelSupport.getChildren( getProject(), WsdlInterface.class ) )
1100 {
1101 endpoints.addAll( iface.getEndpoints() );
1102 }
1103
1104 optionsDialog.setIntValue( OptionsForm.PORT, listenPort );
1105 optionsDialog.setIntValue( OptionsForm.MAXROWS, maxRows );
1106
1107 optionsDialog.setOptions( OptionsForm.REQUEST_WSS,
1108 StringUtils.merge( project.getWssContainer().getIncomingWssNames(), "<none>" ) );
1109 optionsDialog.setOptions( OptionsForm.RESPONSE_WSS,
1110 StringUtils.merge( project.getWssContainer().getIncomingWssNames(), "<none>" ) );
1111
1112 optionsDialog.setValue( OptionsForm.REQUEST_WSS, incomingRequestWss );
1113 optionsDialog.setValue( OptionsForm.RESPONSE_WSS, incomingResponseWss );
1114
1115 if( optionsDialog.show() )
1116 {
1117 Settings settings = getProject().getSettings();
1118
1119 settings.setLong( OptionsForm.PORT, listenPort = optionsDialog.getIntValue( OptionsForm.PORT, listenPort ) );
1120 settings.setLong( OptionsForm.MAXROWS, maxRows = optionsDialog.getIntValue( OptionsForm.MAXROWS, maxRows ) );
1121
1122 incomingRequestWss = optionsDialog.getValue( OptionsForm.REQUEST_WSS );
1123 incomingResponseWss = optionsDialog.getValue( OptionsForm.RESPONSE_WSS );
1124
1125 tableModel.fitSizeToMaxRows();
1126 }
1127 }
1128
1129 @AForm( name = "SOAP Monitor Options", description = "Set options for SOAP Monitor", helpUrl = HelpUrls.SOAPMONITOR_HELP_URL, icon = UISupport.OPTIONS_ICON_PATH )
1130 private class OptionsForm
1131 {
1132 @AField( description = "The local port to listen on", name = "Port", type = AFieldType.INT )
1133 public final static String PORT = "Port";
1134
1135 @AField( description = "The maximum number of exchanges to log", name = "Max Log", type = AFieldType.INT )
1136 public final static String MAXROWS = "Max Log";
1137
1138 @AField( description = "The Incoming WSS configuration to use for processing requests", name = "Incoming Request WSS", type = AFieldType.ENUMERATION )
1139 public final static String REQUEST_WSS = "Incoming Request WSS";
1140
1141 @AField( description = "The Outgoing WSS configuration to use for processing responses", name = "Incoming Response WSS", type = AFieldType.ENUMERATION )
1142 public final static String RESPONSE_WSS = "Incoming Response WSS";
1143 }
1144 }
1145
1146 public void release()
1147 {
1148 requestViewer.release();
1149 responseViewer.release();
1150
1151 if( optionsDialog != null )
1152 {
1153 optionsDialog.release();
1154 optionsDialog = null;
1155 }
1156 }
1157
1158 public boolean isRunning()
1159 {
1160 return monitorEngine.isRunning();
1161 }
1162 }