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