1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.mock;
14
15 import java.awt.BorderLayout;
16 import java.awt.Color;
17 import java.awt.Component;
18 import java.awt.Dimension;
19 import java.awt.event.ActionEvent;
20 import java.awt.event.ActionListener;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.text.SimpleDateFormat;
24 import java.util.ArrayList;
25 import java.util.Date;
26 import java.util.LinkedList;
27 import java.util.List;
28
29 import javax.swing.AbstractAction;
30 import javax.swing.AbstractListModel;
31 import javax.swing.Action;
32 import javax.swing.BorderFactory;
33 import javax.swing.JButton;
34 import javax.swing.JCheckBox;
35 import javax.swing.JComponent;
36 import javax.swing.JLabel;
37 import javax.swing.JList;
38 import javax.swing.JPanel;
39 import javax.swing.JProgressBar;
40 import javax.swing.JScrollPane;
41 import javax.swing.JTextField;
42 import javax.swing.ListCellRenderer;
43 import javax.swing.ListModel;
44 import javax.swing.text.Document;
45
46 import com.eviware.soapui.SoapUI;
47 import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
48 import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation;
49 import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner;
50 import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
51 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
52 import com.eviware.soapui.model.ModelItem;
53 import com.eviware.soapui.model.mock.MockOperation;
54 import com.eviware.soapui.model.mock.MockResponse;
55 import com.eviware.soapui.model.mock.MockResult;
56 import com.eviware.soapui.model.mock.MockServiceListener;
57 import com.eviware.soapui.model.support.MockRunListenerAdapter;
58 import com.eviware.soapui.support.DocumentListenerAdapter;
59 import com.eviware.soapui.support.UISupport;
60 import com.eviware.soapui.support.action.swing.ActionList;
61 import com.eviware.soapui.support.components.JComponentInspector;
62 import com.eviware.soapui.support.components.JInspectorPanel;
63 import com.eviware.soapui.support.components.JXToolBar;
64 import com.eviware.soapui.support.swing.ListMouseListener;
65 import com.eviware.soapui.support.swing.ModelItemListMouseListener;
66 import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
67
68 /***
69 * DesktopPanel for WsdlMockServices
70 *
71 * @author ole.matzura
72 */
73
74 public class WsdlMockServiceDesktopPanel extends ModelItemDesktopPanel<WsdlMockService>
75 {
76 private JButton runButton;
77 private WsdlMockRunner mockRunner;
78 private JButton stopButton;
79 private JProgressBar progressBar;
80 private LogListModel logListModel;
81 private JList testLogList;
82 private JCheckBox enableLogCheckBox;
83 private JScrollPane logScrollPane;
84 private JList operationList;
85 private InternalMockRunListener mockRunListener;
86
87 private JTextField pathTextField;
88 private JTextField portTextField;
89
90 public WsdlMockServiceDesktopPanel( WsdlMockService mockService )
91 {
92 super( mockService );
93 buildUI();
94
95 setPreferredSize( new Dimension( 400, 500 ) );
96
97 mockRunListener = new InternalMockRunListener();
98 mockService.addMockRunListener( mockRunListener );
99 }
100
101 public boolean onClose( boolean canCancel )
102 {
103 if( mockRunner != null && canCancel )
104 {
105 if( !UISupport.confirm( "Close and stop MockService", "Close MockService" ))
106 {
107 return false;
108 }
109 }
110
111 if( mockRunner != null )
112 {
113 mockRunner.stop();
114 mockRunner.release();
115 }
116
117 getModelItem().removeMockRunListener( mockRunListener );
118 ((OperationListModel)operationList.getModel()).release();
119
120 logListModel.clear();
121
122 return release();
123 }
124
125 public boolean dependsOn(ModelItem modelItem)
126 {
127 return modelItem == getModelItem() || modelItem == getModelItem().getProject();
128 }
129
130 private void buildUI()
131 {
132 add( buildToolbar(), BorderLayout.NORTH );
133
134 JInspectorPanel inspectorPanel = new JInspectorPanel( buildOperationList() );
135 inspectorPanel.setDefaultDividerLocation( 0.5F );
136 inspectorPanel.addInspector( new JComponentInspector(
137 buildLog(), "Message Log", "A log of processed requests and their responses", true ));
138
139 inspectorPanel.setCurrentInspector( "Message Log" );
140
141 add( inspectorPanel, BorderLayout.CENTER );
142 add( new JLabel( "--"), BorderLayout.PAGE_END );
143 }
144
145 public boolean logIsEnabled()
146 {
147 return enableLogCheckBox.isSelected();
148 }
149
150 private JComponent buildOperationList()
151 {
152 operationList = new JList( new OperationListModel() );
153 operationList.addMouseListener( new ModelItemListMouseListener() );
154 operationList.setCellRenderer( new OperationListCellRenderer() );
155
156 JScrollPane scrollPane = new JScrollPane( operationList );
157 UISupport.addTitledBorder( scrollPane, "Operations" );
158 return scrollPane;
159 }
160
161 private JComponent buildLog()
162 {
163 JPanel panel = new JPanel( new BorderLayout() );
164 JXToolBar builder = UISupport.createToolbar();
165
166 enableLogCheckBox = new JCheckBox( " ", true);
167 enableLogCheckBox.addActionListener( new ActionListener() {
168
169 public void actionPerformed( ActionEvent arg0 )
170 {
171 testLogList.setEnabled( enableLogCheckBox.isSelected() );
172
173
174 logScrollPane.repaint();
175 }} );
176
177 builder.addFixed( enableLogCheckBox );
178 builder.addRelatedGap();
179 builder.addFixed( new JLabel( "Enable"));
180 builder.addRelatedGap();
181 addLogActions( builder );
182
183 builder.addGlue();
184 builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
185
186 panel.add( builder, BorderLayout.NORTH );
187
188 logListModel = new LogListModel();
189 testLogList = new JList(logListModel);
190 testLogList.setCellRenderer(new LogCellRenderer());
191 testLogList.setPrototypeCellValue( "Testing 123" );
192 testLogList.setFixedCellWidth( -1 );
193 testLogList.addMouseListener(new LogListMouseListener());
194 testLogList.setBorder( BorderFactory.createLineBorder( Color.GRAY ) );
195
196 logScrollPane = new JScrollPane(testLogList);
197
198
199
200 panel.add( logScrollPane, BorderLayout.CENTER );
201
202 return panel;
203 }
204
205 protected void addLogActions( JXToolBar builder )
206 {
207 builder.addFixed( new JButton( new ClearLogAction() ) );
208 builder.addRelatedGap();
209 builder.addFixed( new JButton( new SetLogOptionsAction() ) );
210 }
211
212 private Component buildToolbar()
213 {
214 JXToolBar toolbar = UISupport.createToolbar();
215
216 runButton = createActionButton(new RunMockServiceAction(), true);
217 stopButton = createActionButton(new StopMockServiceAction(), false);
218
219
220 toolbar.addFixed( runButton );
221 toolbar.addFixed( stopButton );
222 toolbar.addUnrelatedGap();
223
224 pathTextField = new JTextField(10);
225 pathTextField.setToolTipText( "The URL path to listen on for this service" );
226 pathTextField.setText( getModelItem().getPath() );
227 pathTextField.setCaretPosition( 0 );
228 pathTextField.getDocument().addDocumentListener( new DocumentListenerAdapter() {
229
230 @Override
231 public void update( Document document )
232 {
233 getModelItem().setPath( pathTextField.getText() );
234 }} );
235
236 toolbar.addLabeledFixed( "Path:", pathTextField );
237 toolbar.addUnrelatedGap();
238
239 portTextField = new JTextField(5);
240 portTextField.setToolTipText( "The local port to listen on for this service" );
241 portTextField.setText( String.valueOf( getModelItem().getPort() ));
242 portTextField.getDocument().addDocumentListener( new DocumentListenerAdapter() {
243
244 @Override
245 public void update( Document document )
246 {
247 try
248 {
249 getModelItem().setPort( Integer.parseInt( portTextField.getText() ) );
250 }
251 catch( Exception e )
252 {
253 }
254 }} );
255
256 toolbar.addLabeledFixed( "Port:", portTextField );
257
258 toolbar.addGlue();
259 progressBar = new JProgressBar();
260 JPanel progressBarPanel = UISupport.createProgressBarPanel( progressBar, 2, false );
261 progressBarPanel.setPreferredSize( new Dimension( 60, 20 ) );
262
263 toolbar.addFixed( progressBarPanel);
264 toolbar.addRelatedGap();
265
266
267 toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKSERVICE_HELP_URL), true ) );
268
269 return toolbar;
270 }
271
272 public void startMockService()
273 {
274 if( mockRunner != null || SoapUI.getMockEngine().hasRunningMock( getModelItem() ) )
275 {
276 UISupport.showErrorMessage( "MockService is already running" );
277 }
278 else
279 {
280 try
281 {
282 mockRunner = getModelItem().start();
283 mockRunner.setMaxResults( logListModel.getMaxSize() );
284 }
285 catch( Exception e )
286 {
287 UISupport.showErrorMessage( e );
288 return;
289 }
290 }
291
292 progressBar.setIndeterminate( true );
293
294 runButton.setEnabled( false );
295 stopButton.setEnabled( true );
296 pathTextField.setEnabled( false );
297 portTextField.setEnabled( false );
298 }
299
300 private final class InternalMockRunListener extends MockRunListenerAdapter
301 {
302 public void onMockResult( MockResult result )
303 {
304 if( logIsEnabled() )
305 {
306 logListModel.addElement( result );
307 }
308 }
309 }
310
311 public class OperationListModel extends AbstractListModel implements ListModel, MockServiceListener, PropertyChangeListener
312 {
313 private List<WsdlMockOperation> operations = new ArrayList<WsdlMockOperation>();
314
315 public OperationListModel()
316 {
317 for( int c = 0; c < getModelItem().getMockOperationCount(); c++ )
318 {
319 WsdlMockOperation mockOperation = ( WsdlMockOperation ) getModelItem().getMockOperationAt( c );
320 mockOperation.addPropertyChangeListener( this );
321
322 operations.add( mockOperation);
323 }
324
325 getModelItem().addMockServiceListener( this );
326 }
327
328 public Object getElementAt( int arg0 )
329 {
330 return operations.get( arg0 );
331 }
332
333 public int getSize()
334 {
335 return operations.size();
336 }
337
338 public void mockOperationAdded( MockOperation operation )
339 {
340 operations.add( ( WsdlMockOperation ) operation );
341 operation.addPropertyChangeListener( this );
342 fireIntervalAdded( this, operations.size()-1, operations.size()-1 );
343 }
344
345 public void mockOperationRemoved( MockOperation operation )
346 {
347 int ix = operations.indexOf( operation );
348 operations.remove( ix );
349 operation.removePropertyChangeListener( this );
350 fireIntervalRemoved( this, ix, ix );
351 }
352
353 public void mockResponseAdded( MockResponse request )
354 {
355 }
356
357 public void mockResponseRemoved( MockResponse request )
358 {
359 }
360
361 public void propertyChange( PropertyChangeEvent arg0 )
362 {
363 if( arg0.getPropertyName().equals( WsdlMockOperation.NAME_PROPERTY ))
364 {
365 int ix = operations.indexOf( arg0.getSource() );
366 fireContentsChanged( this, ix, ix );
367 }
368 }
369
370 public void release()
371 {
372 for( WsdlMockOperation operation : operations )
373 {
374 operation.removePropertyChangeListener( this );
375 }
376
377 getModelItem().removeMockServiceListener( this );
378 }
379 }
380
381 private final static class OperationListCellRenderer extends JLabel implements ListCellRenderer
382 {
383 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
384 boolean cellHasFocus)
385 {
386 MockOperation testStep = (MockOperation) value;
387 setText(testStep.getName());
388 setIcon(testStep.getIcon());
389
390 if (isSelected)
391 {
392 setBackground(list.getSelectionBackground());
393 setForeground(list.getSelectionForeground());
394 }
395 else
396 {
397 setBackground(list.getBackground());
398 setForeground(list.getForeground());
399 }
400
401 setEnabled(list.isEnabled());
402 setFont(list.getFont());
403 setOpaque(true);
404 setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
405
406 return this;
407 }
408 }
409
410 public class RunMockServiceAction extends AbstractAction
411 {
412 public RunMockServiceAction()
413 {
414 putValue(Action.SMALL_ICON, UISupport.createImageIcon("/submit_request.gif"));
415 putValue(Action.SHORT_DESCRIPTION, "Starts this MockService on the specified port and endpoint");
416 putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt ENTER" ));
417 }
418
419 public void actionPerformed( ActionEvent arg0 )
420 {
421 startMockService();
422 }
423 }
424
425 public class StopMockServiceAction extends AbstractAction
426 {
427 public StopMockServiceAction()
428 {
429 putValue(Action.SMALL_ICON, UISupport.createImageIcon("/cancel_request.gif"));
430 putValue(Action.SHORT_DESCRIPTION, "Stops this MockService on the specified port and endpoint");
431 }
432
433 public void actionPerformed( ActionEvent arg0 )
434 {
435 if( mockRunner == null )
436 {
437 UISupport.showErrorMessage( "MockService is not running" );
438 }
439 else
440 {
441 mockRunner.stop();
442 mockRunner.release();
443 mockRunner = null;
444 }
445
446 progressBar.setIndeterminate( false );
447
448 runButton.setEnabled( true );
449 stopButton.setEnabled( false );
450 pathTextField.setEnabled( true );
451 portTextField.setEnabled( true );
452 }
453 }
454
455 private static final class LogCellRenderer extends JLabel implements ListCellRenderer
456 {
457 private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
458
459 public LogCellRenderer()
460 {
461 setOpaque(true);
462 setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
463 }
464
465 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
466 boolean cellHasFocus)
467 {
468 if (value instanceof String)
469 {
470 setText(value.toString());
471 }
472 else if (value instanceof MockResult)
473 {
474 MockResult result = ( MockResult ) value;
475 String msg = dateFormat.format( new Date( result.getTimestamp()) );
476 MockResponse mockResponse = result.getMockResponse();
477
478 if( mockResponse == null )
479 {
480 msg += ": [dispatch error; missing response]";
481 }
482 else
483 {
484 msg += ": [" + mockResponse.getMockOperation().getName();
485 msg += "] " + result.getTimeTaken() + "ms";
486 }
487
488 setText( msg);
489 }
490
491 if (isSelected)
492 {
493 setBackground(list.getSelectionBackground());
494 setForeground(list.getSelectionForeground());
495 }
496 else
497 {
498 setBackground(list.getBackground());
499 setForeground(list.getForeground());
500 }
501
502 setEnabled(list.isEnabled());
503
504 return this;
505 }
506 }
507
508 private class LogListModel extends AbstractListModel
509 {
510 private List<MockResult> elements = new LinkedList<MockResult>();
511 private long maxSize = 100;
512
513 public synchronized void addElement( MockResult result )
514 {
515 elements.add( result );
516 fireIntervalAdded( this, elements.size()-1, elements.size()-1 );
517
518 while( elements.size() > maxSize )
519 {
520 removeElementAt( 0 );
521 }
522 }
523
524 public synchronized Object getElementAt( int index )
525 {
526 return elements.get( index );
527 }
528
529 public synchronized void removeElementAt( int index )
530 {
531 elements.remove( index );
532 fireIntervalRemoved( this, index, index );
533 }
534
535 public synchronized void clear()
536 {
537 int sz = elements.size();
538 if( sz > 0 )
539 {
540 elements.clear();
541 fireIntervalRemoved( this, 0, sz-1 );
542 }
543 }
544
545 public synchronized int getSize()
546 {
547 return elements.size();
548 }
549
550 public long getMaxSize()
551 {
552 return maxSize;
553 }
554
555 public synchronized void setMaxSize( long l )
556 {
557 this.maxSize = l;
558
559 while( elements.size() > maxSize )
560 {
561 removeElementAt( 0 );
562 }
563 }
564 }
565
566 private class SetLogOptionsAction extends AbstractAction
567 {
568 public SetLogOptionsAction()
569 {
570 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ));
571 putValue( Action.SHORT_DESCRIPTION, "Sets MockService Log Options");
572 }
573
574 public void actionPerformed( ActionEvent e )
575 {
576 String s = UISupport.prompt( "Enter maximum number of rows for MockService Log", "Log Options", String.valueOf( logListModel.getMaxSize() ) );
577 if( s != null )
578 {
579 try
580 {
581 logListModel.setMaxSize( Long.parseLong( s ));
582 if( mockRunner != null )
583 mockRunner.setMaxResults( logListModel.getMaxSize() );
584 }
585 catch( NumberFormatException e1 )
586 {
587 }
588 }
589 }}
590
591 private class ClearLogAction extends AbstractAction
592 {
593 public ClearLogAction()
594 {
595 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_loadtest.gif" ));
596 putValue( Action.SHORT_DESCRIPTION, "Clears the MockService Log");
597 }
598
599 public void actionPerformed( ActionEvent e )
600 {
601 logListModel.clear();
602 if( mockRunner != null )
603 mockRunner.clearResults();
604 }}
605
606 /***
607 * Mouse Listener for triggering default action and showing popup for log list items
608 *
609 * @author Ole.Matzura
610 */
611
612 private final class LogListMouseListener extends ListMouseListener
613 {
614 @Override
615 protected ActionList getActionsForRow( JList list, int row )
616 {
617 MockResult result = ( MockResult ) logListModel.getElementAt( row );
618 return result == null ? null : result.getActions();
619 }
620 }
621 }