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.List;
27
28 import javax.swing.AbstractAction;
29 import javax.swing.AbstractListModel;
30 import javax.swing.Action;
31 import javax.swing.BorderFactory;
32 import javax.swing.DefaultListModel;
33 import javax.swing.JButton;
34 import javax.swing.JCheckBox;
35 import javax.swing.JLabel;
36 import javax.swing.JList;
37 import javax.swing.JPanel;
38 import javax.swing.JProgressBar;
39 import javax.swing.JScrollPane;
40 import javax.swing.JSplitPane;
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.WsdlMockService;
50 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
51 import com.eviware.soapui.model.mock.MockOperation;
52 import com.eviware.soapui.model.mock.MockResponse;
53 import com.eviware.soapui.model.mock.MockResult;
54 import com.eviware.soapui.model.mock.MockRunner;
55 import com.eviware.soapui.model.mock.MockServiceListener;
56 import com.eviware.soapui.model.support.MockRunListenerAdapter;
57 import com.eviware.soapui.support.DocumentListenerAdapter;
58 import com.eviware.soapui.support.UISupport;
59 import com.eviware.soapui.support.action.ActionList;
60 import com.eviware.soapui.support.components.JXToolBar;
61 import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
62 import com.jgoodies.forms.builder.ButtonBarBuilder;
63
64 public class WsdlMockServiceDesktopPanel extends ModelItemDesktopPanel<WsdlMockService>
65 {
66 private static final String LOG_TITLE = "Request Log";
67 private JButton runButton;
68 private MockRunner mockRunner;
69 private JButton stopButton;
70 private JProgressBar progressBar;
71 private DefaultListModel logListModel;
72 private JList testLogList;
73 private JCheckBox enableLogCheckBox;
74 private JScrollPane logScrollPane;
75 private JList operationList;
76 private InternalMockRunListener mockRunListener;
77
78 private JTextField pathTextField;
79 private JTextField portTextField;
80
81 public WsdlMockServiceDesktopPanel( WsdlMockService mockService )
82 {
83 super( mockService );
84 buildUI();
85
86 setPreferredSize( new Dimension( 350, 500 ) );
87
88 mockRunListener = new InternalMockRunListener();
89 mockService.addMockRunListener( mockRunListener );
90 }
91
92 public boolean onClose( boolean canCancel )
93 {
94 if( mockRunner != null && canCancel )
95 {
96 if( !UISupport.confirm( "Close and stop MockService", "Close MockService" ))
97 {
98 return false;
99 }
100 }
101
102 if( mockRunner != null )
103 {
104 mockRunner.stop();
105 }
106
107 getModelItem().removeMockRunListener( mockRunListener );
108 ((OperationListModel)operationList.getModel()).release();
109
110 return release();
111 }
112
113 private void buildUI()
114 {
115 add( buildToolbar(), BorderLayout.NORTH );
116
117 JSplitPane splitPane = UISupport.createVerticalSplit();
118 splitPane.setTopComponent( buildOperationList() );
119 splitPane.setBottomComponent( buildLog() );
120 splitPane.setDividerLocation( 0.7 );
121 splitPane.setDividerLocation( 250 );
122
123 add( splitPane, BorderLayout.CENTER );
124 add( new JLabel( "--"), BorderLayout.PAGE_END );
125 }
126
127 public boolean logIsEnabled()
128 {
129 return enableLogCheckBox.isSelected();
130 }
131
132 private Component buildOperationList()
133 {
134 JPanel panel = new JPanel( new BorderLayout() );
135 ButtonBarBuilder builder = new ButtonBarBuilder();
136
137 enableLogCheckBox = new JCheckBox("Enable Log", true);
138 enableLogCheckBox.addActionListener( new ActionListener() {
139
140 public void actionPerformed( ActionEvent arg0 )
141 {
142 testLogList.setEnabled( !enableLogCheckBox.isSelected() );
143
144
145 logScrollPane.repaint();
146 }} );
147
148 builder.addFixed( enableLogCheckBox );
149 builder.addGlue();
150
151 progressBar = new JProgressBar();
152 JPanel progressBarPanel = UISupport.createProgressBarPanel( progressBar, 2, false );
153 progressBarPanel.setPreferredSize( new Dimension( 60, 20 ) );
154
155 builder.addFixed( progressBarPanel);
156 builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
157
158 panel.add( builder.getPanel(), BorderLayout.NORTH );
159
160 operationList = new JList( new OperationListModel() );
161 operationList.addMouseListener( new ModelItemListMouseListener() );
162 operationList.setCellRenderer( new OperationListCellRenderer() );
163
164 JScrollPane scrollPane = new JScrollPane( operationList );
165 UISupport.addTitledBorder( scrollPane, "Operations" );
166 panel.add( scrollPane, BorderLayout.CENTER );
167
168 return panel;
169 }
170
171 private Component buildLog()
172 {
173 logListModel = new DefaultListModel();
174 testLogList = new JList(logListModel);
175 testLogList.setCellRenderer(new LogCellRenderer());
176 testLogList.addMouseListener(new LogListMouseListener());
177 testLogList.setBorder( BorderFactory.createLineBorder( Color.GRAY ) );
178
179 logScrollPane = new JScrollPane(testLogList);
180 logScrollPane.setBorder( null );
181 UISupport.addTitledBorder( logScrollPane, LOG_TITLE );
182 return logScrollPane;
183 }
184
185 private Component buildToolbar()
186 {
187 JXToolBar toolbar = UISupport.createToolbar();
188
189 runButton = createActionButton(new RunMockServiceAction(), true);
190 stopButton = createActionButton(new StopMockServiceAction(), false);
191
192
193 toolbar.addFixed( runButton );
194 toolbar.addFixed( stopButton );
195 toolbar.addUnrelatedGap();
196
197 pathTextField = new JTextField(15);
198 pathTextField.setToolTipText( "The URL path to listen on for this service" );
199 pathTextField.setText( getModelItem().getPath() );
200 pathTextField.setCaretPosition( 0 );
201 pathTextField.getDocument().addDocumentListener( new DocumentListenerAdapter() {
202
203 @Override
204 public void update( Document document )
205 {
206 getModelItem().setPath( pathTextField.getText() );
207 }} );
208
209 toolbar.addLabeledFixed( "Path:", pathTextField );
210 toolbar.addUnrelatedGap();
211
212 portTextField = new JTextField(5);
213 portTextField.setToolTipText( "The local port to listen on for this service" );
214 portTextField.setText( String.valueOf( getModelItem().getPort() ));
215 portTextField.getDocument().addDocumentListener( new DocumentListenerAdapter() {
216
217 @Override
218 public void update( Document document )
219 {
220 try
221 {
222 getModelItem().setPort( Integer.parseInt( portTextField.getText() ) );
223 }
224 catch( Exception e )
225 {
226 }
227 }} );
228
229 toolbar.addLabeledFixed( "Port:", portTextField );
230
231 toolbar.addGlue();
232
233 toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKSERVICE_HELP_URL), true ) );
234
235 return toolbar;
236 }
237
238 private final class InternalMockRunListener extends MockRunListenerAdapter
239 {
240 public void onMockResult( MockResult result )
241 {
242 if( logIsEnabled() )
243 {
244 logListModel.addElement( result );
245 }
246 }
247 }
248
249 public class OperationListModel extends AbstractListModel implements ListModel, MockServiceListener, PropertyChangeListener
250 {
251 private List<WsdlMockOperation> operations = new ArrayList<WsdlMockOperation>();
252
253 public OperationListModel()
254 {
255 for( int c = 0; c < getModelItem().getMockOperationCount(); c++ )
256 {
257 WsdlMockOperation mockOperation = ( WsdlMockOperation ) getModelItem().getMockOperationAt( c );
258 mockOperation.addPropertyChangeListener( this );
259
260 operations.add( mockOperation);
261 }
262
263 getModelItem().addMockServiceListener( this );
264 }
265
266 public Object getElementAt( int arg0 )
267 {
268 return operations.get( arg0 );
269 }
270
271 public int getSize()
272 {
273 return operations.size();
274 }
275
276 public void mockOperationAdded( MockOperation operation )
277 {
278 operations.add( ( WsdlMockOperation ) operation );
279 operation.addPropertyChangeListener( this );
280 fireIntervalAdded( this, operations.size()-1, operations.size()-1 );
281 }
282
283 public void mockOperationRemoved( MockOperation operation )
284 {
285 int ix = operations.indexOf( operation );
286 operations.remove( ix );
287 operation.removePropertyChangeListener( this );
288 fireIntervalRemoved( this, ix, ix );
289 }
290
291 public void mockResponseAdded( MockResponse request )
292 {
293 }
294
295 public void mockResponseRemoved( MockResponse request )
296 {
297 }
298
299 public void propertyChange( PropertyChangeEvent arg0 )
300 {
301 if( arg0.getPropertyName().equals( WsdlMockOperation.NAME_PROPERTY ))
302 {
303 int ix = operations.indexOf( arg0.getSource() );
304 fireContentsChanged( this, ix, ix );
305 }
306 }
307
308 public void release()
309 {
310 for( WsdlMockOperation operation : operations )
311 {
312 operation.removePropertyChangeListener( this );
313 }
314
315 getModelItem().removeMockServiceListener( this );
316 }
317 }
318
319 private final static class OperationListCellRenderer extends JLabel implements ListCellRenderer
320 {
321 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
322 boolean cellHasFocus)
323 {
324 MockOperation testStep = (MockOperation) value;
325 setText(testStep.getName());
326 setIcon(testStep.getIcon());
327
328 if (isSelected)
329 {
330 setBackground(list.getSelectionBackground());
331 setForeground(list.getSelectionForeground());
332 }
333 else
334 {
335 setBackground(list.getBackground());
336 setForeground(list.getForeground());
337 }
338
339 setEnabled(list.isEnabled());
340 setFont(list.getFont());
341 setOpaque(true);
342 setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
343
344 return this;
345 }
346 }
347
348 public class RunMockServiceAction extends AbstractAction
349 {
350 public RunMockServiceAction()
351 {
352 putValue(Action.SMALL_ICON, UISupport.createImageIcon("/submit_request.gif"));
353 putValue(Action.SHORT_DESCRIPTION, "Starts this MockService on the specified port and endpoint");
354 putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt ENTER" ));
355 }
356
357 public void actionPerformed( ActionEvent arg0 )
358 {
359 if( mockRunner != null || SoapUI.getMockEngine().hasRunningMock( getModelItem() ) )
360 {
361 UISupport.showErrorMessage( "MockService is already running" );
362 }
363 else
364 {
365 try
366 {
367 mockRunner = getModelItem().start();
368 }
369 catch( Exception e )
370 {
371 UISupport.showErrorMessage( e );
372 e.printStackTrace();
373 return;
374 }
375 }
376
377 progressBar.setIndeterminate( true );
378
379 runButton.setEnabled( false );
380 stopButton.setEnabled( true );
381 pathTextField.setEnabled( false );
382 portTextField.setEnabled( false );
383 }
384 }
385
386 public class StopMockServiceAction extends AbstractAction
387 {
388 public StopMockServiceAction()
389 {
390 putValue(Action.SMALL_ICON, UISupport.createImageIcon("/cancel_request.gif"));
391 putValue(Action.SHORT_DESCRIPTION, "Stops this MockService on the specified port and endpoint");
392 }
393
394 public void actionPerformed( ActionEvent arg0 )
395 {
396 if( mockRunner == null )
397 {
398 UISupport.showErrorMessage( "MockService is not running" );
399 }
400 else
401 {
402 mockRunner.stop();
403 mockRunner = null;
404 }
405
406 progressBar.setIndeterminate( false );
407
408 runButton.setEnabled( true );
409 stopButton.setEnabled( false );
410 pathTextField.setEnabled( true );
411 portTextField.setEnabled( true );
412 }
413 }
414
415 private static final class LogCellRenderer extends JLabel implements ListCellRenderer
416 {
417 private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
418
419 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
420 boolean cellHasFocus)
421 {
422 setIcon(null);
423
424 if (value instanceof String)
425 {
426 setText(value.toString());
427 }
428 else if (value instanceof MockResult)
429 {
430 MockResult result = ( MockResult ) value;
431 setIcon(null);
432 String msg = dateFormat.format( new Date( result.getTimestamp()) );
433 MockResponse mockResponse = result.getMockResponse();
434
435 if( mockResponse == null )
436 {
437 msg += ": [dispatch error; missing response]";
438 }
439 else
440 {
441 msg += ": [" + mockResponse.getMockOperation().getName();
442 msg += "] " + result.getTimeTaken() + "ms";
443 }
444
445 setText( msg);
446 }
447
448 if (isSelected)
449 {
450 setBackground(list.getSelectionBackground());
451 setForeground(list.getSelectionForeground());
452 }
453 else
454 {
455 setBackground(list.getBackground());
456 setForeground(list.getForeground());
457 }
458
459 setEnabled(list.isEnabled());
460 setFont(list.getFont());
461 setOpaque(true);
462 setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
463
464 return this;
465 }
466 }
467
468 /***
469 * Mouse Listener for triggering default action and showing popup for log list items
470 *
471 * @author Ole.Matzura
472 */
473
474 private final class LogListMouseListener extends ListMouseListener
475 {
476 @Override
477 protected ActionList getActionsForRow( JList list, int row )
478 {
479 MockResult result = ( MockResult ) logListModel.getElementAt( row );
480 return result == null ? null : result.getActions();
481 }
482 }
483 }