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