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