View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
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.Collections;
26  import java.util.Date;
27  import java.util.LinkedList;
28  import java.util.List;
29  
30  import javax.swing.AbstractAction;
31  import javax.swing.AbstractListModel;
32  import javax.swing.Action;
33  import javax.swing.BorderFactory;
34  import javax.swing.JButton;
35  import javax.swing.JCheckBox;
36  import javax.swing.JComponent;
37  import javax.swing.JLabel;
38  import javax.swing.JList;
39  import javax.swing.JPanel;
40  import javax.swing.JProgressBar;
41  import javax.swing.JScrollPane;
42  import javax.swing.JTabbedPane;
43  import javax.swing.ListCellRenderer;
44  import javax.swing.ListModel;
45  import javax.swing.SwingConstants;
46  import javax.swing.text.Document;
47  
48  import com.eviware.soapui.SoapUI;
49  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
50  import com.eviware.soapui.impl.wsdl.actions.mockservice.AddNewMockOperationAction;
51  import com.eviware.soapui.impl.wsdl.actions.mockservice.MockServiceOptionsAction;
52  import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation;
53  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunContext;
54  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner;
55  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
56  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
57  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
58  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
59  import com.eviware.soapui.model.ModelItem;
60  import com.eviware.soapui.model.mock.MockOperation;
61  import com.eviware.soapui.model.mock.MockResponse;
62  import com.eviware.soapui.model.mock.MockResult;
63  import com.eviware.soapui.model.mock.MockRunner;
64  import com.eviware.soapui.model.mock.MockServiceListener;
65  import com.eviware.soapui.model.support.MockRunListenerAdapter;
66  import com.eviware.soapui.settings.UISettings;
67  import com.eviware.soapui.support.DocumentListenerAdapter;
68  import com.eviware.soapui.support.StringUtils;
69  import com.eviware.soapui.support.Tools;
70  import com.eviware.soapui.support.UISupport;
71  import com.eviware.soapui.support.action.swing.ActionList;
72  import com.eviware.soapui.support.action.swing.DefaultActionList;
73  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
74  import com.eviware.soapui.support.components.GroovyEditorComponent;
75  import com.eviware.soapui.support.components.GroovyEditorInspector;
76  import com.eviware.soapui.support.components.JComponentInspector;
77  import com.eviware.soapui.support.components.JFocusableComponentInspector;
78  import com.eviware.soapui.support.components.JInspectorPanel;
79  import com.eviware.soapui.support.components.JInspectorPanelFactory;
80  import com.eviware.soapui.support.components.JUndoableTextArea;
81  import com.eviware.soapui.support.components.JXToolBar;
82  import com.eviware.soapui.support.swing.AbstractListMouseListener;
83  import com.eviware.soapui.support.swing.ModelItemListKeyListener;
84  import com.eviware.soapui.support.swing.ModelItemListMouseListener;
85  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
86  
87  /***
88   * DesktopPanel for WsdlMockServices
89   * 
90   * @author ole.matzura
91   */
92  
93  public class WsdlMockServiceDesktopPanel extends ModelItemDesktopPanel<WsdlMockService>
94  {
95  	private JButton runButton;
96  	private WsdlMockRunner mockRunner;
97  	private JButton stopButton;
98  	private JProgressBar progressBar;
99  	private LogListModel logListModel;
100 	private JList testLogList;
101 	private JCheckBox enableLogCheckBox;
102 	private JScrollPane logScrollPane;
103 	private JList operationList;
104 	private InternalMockRunListener mockRunListener;
105 	private PropertyHolderTable propertiesTable;
106 	private JUndoableTextArea descriptionArea;
107 	private JButton showWsdlButton;
108 	private JButton optionsButton;
109 	private JLabel runInfoLabel;
110 	private GroovyEditorComponent startGroovyEditor;
111 	private GroovyEditorComponent stopGroovyEditor;
112 	private GroovyEditorComponent onRequestGroovyEditor;
113 	private GroovyEditorComponent afterRequestGroovyEditor;
114 	private JInspectorPanel inspectorPanel;
115 	private JInspectorPanel contentInspector;
116 
117 	public WsdlMockServiceDesktopPanel( WsdlMockService mockService )
118 	{
119 		super( mockService );
120 		buildUI();
121 
122 		setPreferredSize( new Dimension( 400, 500 ) );
123 
124 		mockRunListener = new InternalMockRunListener();
125 		mockService.addMockRunListener( mockRunListener );
126 	}
127 
128 	public boolean onClose( boolean canCancel )
129 	{
130 		if( mockRunner != null && mockRunner.isRunning() && canCancel )
131 		{
132 			if( !UISupport.confirm( "Close and stop MockService", "Close MockService" ) )
133 			{
134 				return false;
135 			}
136 		}
137 
138 		if( mockRunner != null )
139 		{
140 			if( mockRunner.isRunning() )
141 				mockRunner.stop();
142 
143 			mockRunner.release();
144 		}
145 
146 		getModelItem().removeMockRunListener( mockRunListener );
147 		( ( OperationListModel )operationList.getModel() ).release();
148 
149 		logListModel.clear();
150 		propertiesTable.release();
151 
152 		startGroovyEditor.getEditor().release();
153 		stopGroovyEditor.getEditor().release();
154 
155 		inspectorPanel.release();
156 		contentInspector.release();
157 		return release();
158 	}
159 
160 	public boolean dependsOn( ModelItem modelItem )
161 	{
162 		return modelItem == getModelItem() || modelItem == getModelItem().getProject();
163 	}
164 
165 	private void buildUI()
166 	{
167 		add( buildToolbar(), BorderLayout.NORTH );
168 
169 		contentInspector = JInspectorPanelFactory.build( buildContent() );
170 		contentInspector.setDefaultDividerLocation( 0.5F );
171 		contentInspector.addInspector( new JComponentInspector<JComponent>( buildLog(), "Message Log",
172 				"A log of processed requests and their responses", true ) );
173 
174 		contentInspector.setCurrentInspector( "Message Log" );
175 
176 		add( contentInspector.getComponent(), BorderLayout.CENTER );
177 		add( new JLabel( "--" ), BorderLayout.PAGE_END );
178 	}
179 
180 	public boolean logIsEnabled()
181 	{
182 		return enableLogCheckBox.isSelected();
183 	}
184 
185 	private JComponent buildContent()
186 	{
187 		JTabbedPane tabs = new JTabbedPane();
188 		inspectorPanel = JInspectorPanelFactory.build( buildOperationList() );
189 
190 		tabs.addTab( "Operations", inspectorPanel.getComponent() );
191 		addTabs( tabs, inspectorPanel );
192 
193 		if( StringUtils.hasContent( getModelItem().getDescription() )
194 				&& getModelItem().getSettings().getBoolean( UISettings.SHOW_DESCRIPTIONS ) )
195 		{
196 			inspectorPanel.setCurrentInspector( "Description" );
197 		}
198 
199 		return UISupport.createTabPanel( tabs, true );
200 	}
201 
202 	protected void addTabs( JTabbedPane tabs, JInspectorPanel inspectorPanel )
203 	{
204 		inspectorPanel.addInspector( new JFocusableComponentInspector<JPanel>( buildDescriptionPanel(), descriptionArea,
205 				"Description", "A description for this MockService", true ) );
206 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildPropertiesPanel(), "Properties",
207 				"Properties for this MockService", true ) );
208 		inspectorPanel.addInspector( new GroovyEditorInspector( buildStartScriptPanel(), "Start Script",
209 				"A Groovy script to run when starting the MockService" ) );
210 		inspectorPanel.addInspector( new GroovyEditorInspector( buildStopScriptPanel(), "Stop Script",
211 				"A Groovy script to run when stopping the MockService" ) );
212 		inspectorPanel.addInspector( new GroovyEditorInspector( buildOnRequestScriptPanel(), "OnRequest Script",
213 				"A Groovy script to run when receiving a request before it is dispatched" ) );
214 		inspectorPanel.addInspector( new GroovyEditorInspector( buildAfterRequestScriptPanel(), "AfterRequest Script",
215 				"A Groovy script to run after a request has been dispatched" ) );
216 	}
217 
218 	protected JComponent buildOperationList()
219 	{
220 		operationList = new JList( new OperationListModel() );
221 		operationList.addMouseListener( new ModelItemListMouseListener()
222 		{
223 			private ActionList defaultActions;
224 
225 			protected ActionList getDefaultActions()
226 			{
227 				if( defaultActions == null )
228 				{
229 					defaultActions = new DefaultActionList();
230 					defaultActions.addAction( SwingActionDelegate.createDelegate(
231 							AddNewMockOperationAction.SOAPUI_ACTION_ID, getModelItem(), null, null ) );
232 				}
233 
234 				return defaultActions;
235 			}
236 		} );
237 		operationList.setCellRenderer( new OperationListCellRenderer() );
238 		operationList.addKeyListener( new ModelItemListKeyListener()
239 		{
240 
241 			@Override
242 			public ModelItem getModelItemAt( int ix )
243 			{
244 				return getModelItem().getMockOperationAt( ix );
245 			}
246 		} );
247 
248 		JScrollPane scrollPane = new JScrollPane( operationList );
249 		return UISupport.buildPanelWithToolbar( buildMockOperationListToolbar(), scrollPane );
250 	}
251 
252 	private JComponent buildMockOperationListToolbar()
253 	{
254 		JXToolBar toolbar = UISupport.createToolbar();
255 		toolbar.add( UISupport.createToolbarButton( SwingActionDelegate.createDelegate(
256 				AddNewMockOperationAction.SOAPUI_ACTION_ID, getModelItem(), null, "/mockOperation.gif" ) ) );
257 
258 		return toolbar;
259 	}
260 
261 	protected JComponent buildPropertiesPanel()
262 	{
263 		JPanel panel = new JPanel( new BorderLayout() );
264 		propertiesTable = new PropertyHolderTable( getModelItem() );
265 		panel.add( new JScrollPane( propertiesTable ), BorderLayout.CENTER );
266 		return panel;
267 	}
268 
269 	protected GroovyEditorComponent buildStartScriptPanel()
270 	{
271 		startGroovyEditor = new GroovyEditorComponent( new StartScriptGroovyEditorModel(), null );
272 		return startGroovyEditor;
273 	}
274 
275 	protected GroovyEditorComponent buildStopScriptPanel()
276 	{
277 		stopGroovyEditor = new GroovyEditorComponent( new StopScriptGroovyEditorModel(), null );
278 		return stopGroovyEditor;
279 	}
280 
281 	protected GroovyEditorComponent buildOnRequestScriptPanel()
282 	{
283 		onRequestGroovyEditor = new GroovyEditorComponent( new OnRequestScriptGroovyEditorModel(), null );
284 		return onRequestGroovyEditor;
285 	}
286 
287 	protected GroovyEditorComponent buildAfterRequestScriptPanel()
288 	{
289 		afterRequestGroovyEditor = new GroovyEditorComponent( new AfterRequestScriptGroovyEditorModel(), null );
290 		return afterRequestGroovyEditor;
291 	}
292 
293 	protected JPanel buildDescriptionPanel()
294 	{
295 		JPanel panel = new JPanel( new BorderLayout() );
296 		descriptionArea = new JUndoableTextArea( getModelItem().getDescription() );
297 		descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter()
298 		{
299 			public void update( Document document )
300 			{
301 				getModelItem().setDescription( descriptionArea.getText() );
302 			}
303 		} );
304 
305 		panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
306 		UISupport.addTitledBorder( panel, "MockService Description" );
307 		panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
308 
309 		return panel;
310 	}
311 
312 	protected JComponent buildLog()
313 	{
314 		JPanel panel = new JPanel( new BorderLayout() );
315 		JXToolBar builder = UISupport.createToolbar();
316 
317 		enableLogCheckBox = new JCheckBox( " ", true );
318 		enableLogCheckBox.addActionListener( new ActionListener()
319 		{
320 
321 			public void actionPerformed( ActionEvent arg0 )
322 			{
323 				testLogList.setEnabled( enableLogCheckBox.isSelected() );
324 				if( mockRunner != null )
325 					mockRunner.setLogEnabled( enableLogCheckBox.isSelected() );
326 
327 				// border needs to be repainted..
328 				logScrollPane.repaint();
329 			}
330 		} );
331 		enableLogCheckBox.setOpaque( false );
332 
333 		builder.addFixed( enableLogCheckBox );
334 		builder.addRelatedGap();
335 		builder.addFixed( new JLabel( "Enable" ) );
336 		builder.addRelatedGap();
337 		addLogActions( builder );
338 
339 		builder.addGlue();
340 		builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
341 
342 		panel.add( builder, BorderLayout.NORTH );
343 
344 		logListModel = new LogListModel();
345 		testLogList = new JList( logListModel );
346 		testLogList.setCellRenderer( new LogCellRenderer() );
347 		testLogList.setPrototypeCellValue( "Testing 123" );
348 		testLogList.setFixedCellWidth( -1 );
349 		testLogList.addMouseListener( new LogListMouseListener() );
350 		testLogList.setBorder( BorderFactory.createLineBorder( Color.GRAY ) );
351 
352 		logScrollPane = new JScrollPane( testLogList );
353 
354 		panel.add( logScrollPane, BorderLayout.CENTER );
355 
356 		return panel;
357 	}
358 
359 	protected void addLogActions( JXToolBar builder )
360 	{
361 		builder.addFixed( UISupport.createToolbarButton( new ClearLogAction() ) );
362 		builder.addRelatedGap();
363 		builder.addFixed( UISupport.createToolbarButton( new SetLogOptionsAction() ) );
364 	}
365 
366 	protected JXToolBar buildToolbar()
367 	{
368 		JXToolBar toolbar = UISupport.createToolbar();
369 
370 		runButton = createActionButton( new RunMockServiceAction(), true );
371 		stopButton = createActionButton( new StopMockServiceAction(), false );
372 		optionsButton = createActionButton( SwingActionDelegate.createDelegate( new MockServiceOptionsAction(),
373 				getModelItem(), null, "/options.gif" ), true );
374 		showWsdlButton = createActionButton( new ShowWsdlAction(), false );
375 
376 		toolbar.addFixed( runButton );
377 		toolbar.addFixed( stopButton );
378 		toolbar.addFixed( showWsdlButton );
379 		toolbar.addFixed( optionsButton );
380 
381 		toolbar.addGlue();
382 
383 		runInfoLabel = new JLabel( "", SwingConstants.RIGHT );
384 		toolbar.addFixed( UISupport.setFixedSize( runInfoLabel, 200, 20 ) );
385 		toolbar.addRelatedGap();
386 
387 		progressBar = new JProgressBar();
388 		JPanel progressBarPanel = UISupport.createProgressBarPanel( progressBar, 2, false );
389 		progressBarPanel.setPreferredSize( new Dimension( 60, 20 ) );
390 
391 		toolbar.addFixed( progressBarPanel );
392 		toolbar.addRelatedGap();
393 
394 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction( HelpUrls.MOCKSERVICE_HELP_URL ), true ) );
395 
396 		return toolbar;
397 	}
398 
399 	public void startMockService()
400 	{
401 		if( ( mockRunner != null && mockRunner.isRunning() ) || SoapUI.getMockEngine().hasRunningMock( getModelItem() ) )
402 		{
403 			UISupport.showErrorMessage( "MockService is already running" );
404 		}
405 		else
406 		{
407 			if( mockRunner != null )
408 				mockRunner.release();
409 
410 			try
411 			{
412 				getModelItem().start();
413 			}
414 			catch( Exception e )
415 			{
416 				UISupport.showErrorMessage( e );
417 				return;
418 			}
419 		}
420 	}
421 
422 	private final class InternalMockRunListener extends MockRunListenerAdapter
423 	{
424 		@Override
425 		public void onMockRunnerStart( MockRunner runner )
426 		{
427 			mockRunner = ( WsdlMockRunner )runner;
428 			mockRunner.setMaxResults( logListModel.getMaxSize() );
429 			mockRunner.setLogEnabled( enableLogCheckBox.isSelected() );
430 
431 			progressBar.setIndeterminate( true );
432 
433 			runButton.setEnabled( false );
434 			stopButton.setEnabled( true );
435 			optionsButton.setEnabled( false );
436 			showWsdlButton.setEnabled( true );
437 
438 			runInfoLabel.setText( "running on port " + getModelItem().getPort() );
439 		}
440 
441 		@Override
442 		public void onMockRunnerStop( MockRunner mockRunner )
443 		{
444 			progressBar.setIndeterminate( false );
445 
446 			runButton.setEnabled( true );
447 			stopButton.setEnabled( false );
448 			optionsButton.setEnabled( true );
449 			showWsdlButton.setEnabled( false );
450 
451 			runInfoLabel.setText( "" );
452 		}
453 
454 		public void onMockResult( MockResult result )
455 		{
456 			if( logIsEnabled() )
457 			{
458 				logListModel.addElement( result );
459 			}
460 		}
461 	}
462 
463 	public class OperationListModel extends AbstractListModel implements ListModel, MockServiceListener,
464 			PropertyChangeListener
465 	{
466 		private List<WsdlMockOperation> operations = new ArrayList<WsdlMockOperation>();
467 
468 		public OperationListModel()
469 		{
470 			for( int c = 0; c < getModelItem().getMockOperationCount(); c++ )
471 			{
472 				WsdlMockOperation mockOperation = getModelItem().getMockOperationAt( c );
473 				mockOperation.addPropertyChangeListener( this );
474 
475 				operations.add( mockOperation );
476 			}
477 
478 			getModelItem().addMockServiceListener( this );
479 		}
480 
481 		public Object getElementAt( int arg0 )
482 		{
483 			return operations.get( arg0 );
484 		}
485 
486 		public int getSize()
487 		{
488 			return operations.size();
489 		}
490 
491 		public void mockOperationAdded( MockOperation operation )
492 		{
493 			operations.add( ( WsdlMockOperation )operation );
494 			operation.addPropertyChangeListener( this );
495 			fireIntervalAdded( this, operations.size() - 1, operations.size() - 1 );
496 		}
497 
498 		public void mockOperationRemoved( MockOperation operation )
499 		{
500 			int ix = operations.indexOf( operation );
501 			operations.remove( ix );
502 			operation.removePropertyChangeListener( this );
503 			fireIntervalRemoved( this, ix, ix );
504 		}
505 
506 		public void mockResponseAdded( MockResponse request )
507 		{
508 		}
509 
510 		public void mockResponseRemoved( MockResponse request )
511 		{
512 		}
513 
514 		public void propertyChange( PropertyChangeEvent arg0 )
515 		{
516 			if( arg0.getPropertyName().equals( WsdlMockOperation.NAME_PROPERTY ) )
517 			{
518 				int ix = operations.indexOf( arg0.getSource() );
519 				fireContentsChanged( this, ix, ix );
520 			}
521 		}
522 
523 		public void release()
524 		{
525 			for( WsdlMockOperation operation : operations )
526 			{
527 				operation.removePropertyChangeListener( this );
528 			}
529 
530 			getModelItem().removeMockServiceListener( this );
531 		}
532 	}
533 
534 	private final static class OperationListCellRenderer extends JLabel implements ListCellRenderer
535 	{
536 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected,
537 				boolean cellHasFocus )
538 		{
539 			MockOperation testStep = ( MockOperation )value;
540 			setText( testStep.getName() );
541 			setIcon( testStep.getIcon() );
542 
543 			if( isSelected )
544 			{
545 				setBackground( list.getSelectionBackground() );
546 				setForeground( list.getSelectionForeground() );
547 			}
548 			else
549 			{
550 				setBackground( list.getBackground() );
551 				setForeground( list.getForeground() );
552 			}
553 
554 			setEnabled( list.isEnabled() );
555 			setFont( list.getFont() );
556 			setOpaque( true );
557 			setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
558 
559 			return this;
560 		}
561 	}
562 
563 	public class RunMockServiceAction extends AbstractAction
564 	{
565 		public RunMockServiceAction()
566 		{
567 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/submit_request.gif" ) );
568 			putValue( Action.SHORT_DESCRIPTION, "Starts this MockService on the specified port and endpoint" );
569 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt ENTER" ) );
570 		}
571 
572 		public void actionPerformed( ActionEvent arg0 )
573 		{
574 			startMockService();
575 		}
576 	}
577 
578 	public class ShowWsdlAction extends AbstractAction
579 	{
580 		public ShowWsdlAction()
581 		{
582 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/interface.gif" ) );
583 			putValue( Action.SHORT_DESCRIPTION, "Opens the root WSDL page in a browser" );
584 		}
585 
586 		public void actionPerformed( ActionEvent arg0 )
587 		{
588 			WsdlMockService mockService = getModelItem();
589 			Tools.openURL( mockService.getLocalEndpoint() + "?WSDL" );
590 		}
591 	}
592 
593 	public class StopMockServiceAction extends AbstractAction
594 	{
595 		public StopMockServiceAction()
596 		{
597 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/cancel_request.gif" ) );
598 			putValue( Action.SHORT_DESCRIPTION, "Stops this MockService on the specified port and endpoint" );
599 		}
600 
601 		public void actionPerformed( ActionEvent arg0 )
602 		{
603 			if( mockRunner == null )
604 			{
605 				UISupport.showErrorMessage( "MockService is not running" );
606 			}
607 			else
608 			{
609 				mockRunner.stop();
610 				mockRunner.release();
611 				mockRunner = null;
612 			}
613 		}
614 	}
615 
616 	private static final class LogCellRenderer extends JLabel implements ListCellRenderer
617 	{
618 		private SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
619 
620 		public LogCellRenderer()
621 		{
622 			setOpaque( true );
623 			setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
624 		}
625 
626 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected,
627 				boolean cellHasFocus )
628 		{
629 			setText( value.toString() );
630 			
631 			if( isSelected )
632 			{
633 				setBackground( list.getSelectionBackground() );
634 				setForeground( list.getSelectionForeground() );
635 			}
636 			else
637 			{
638 				setBackground( list.getBackground() );
639 				setForeground( list.getForeground() );
640 			}
641 
642 			setEnabled( list.isEnabled() );
643 
644 			return this;
645 		}
646 	}
647 
648 	private long getDefaultMaxSize()
649 	{
650 		return getModelItem().getSettings().getLong( LogListModel.class.getName() + "@maxSize", 100 );
651 	}
652 
653 	protected long getMaxLogSize()
654 	{
655 		if( logListModel != null )
656 			return logListModel.getMaxSize();
657 		else
658 			return getDefaultMaxSize();
659 	}
660 
661 	protected void setMaxLogSize( long size )
662 	{
663 		logListModel.setMaxSize( size );
664 		if( mockRunner != null )
665 			mockRunner.setMaxResults( logListModel.getMaxSize() );
666 	}
667 
668 	private class LogListModel extends AbstractListModel
669 	{
670 		private List<MockResult> elements = Collections.synchronizedList( new LinkedList<MockResult>() );
671 		private long maxSize;
672 
673 		public LogListModel()
674 		{
675 			maxSize = getDefaultMaxSize();
676 		}
677 
678 		public void addElement( MockResult result )
679 		{
680 			elements.add( result );
681 			fireIntervalAdded( this, elements.size() - 1, elements.size() - 1 );
682 
683 			synchronized( this )
684 			{
685 				while( elements.size() > maxSize )
686 				{
687 					removeElementAt( 0 );
688 				}
689 			}
690 		}
691 
692 		public Object getElementAt( int index )
693 		{
694 			synchronized( this )
695 			{
696 				if(elements.size() <= index) return null;
697 				return elements.get( index );
698 			}
699 		}
700 
701 		public void removeElementAt( int index )
702 		{
703 			elements.remove( index );
704 			fireIntervalRemoved( this, index, index );
705 		}
706 
707 		public void clear()
708 		{
709 			synchronized( this )
710 			{
711 				int sz = elements.size();
712 				if( sz > 0 )
713 				{
714 					elements.clear();
715 					fireIntervalRemoved( this, 0, sz - 1 );
716 				}
717 			}
718 		}
719 
720 		public int getSize()
721 		{
722 			return elements.size();
723 		}
724 
725 		public long getMaxSize()
726 		{
727 			return maxSize;
728 		}
729 
730 		public synchronized void setMaxSize( long l )
731 		{
732 			this.maxSize = l;
733 
734 			while( elements.size() > 0 && elements.size() > maxSize )
735 			{
736 				removeElementAt( 0 );
737 			}
738 
739 			getModelItem().getSettings().setLong( LogListModel.class.getName() + "@maxSize", maxSize );
740 		}
741 	}
742 
743 	private class SetLogOptionsAction extends AbstractAction
744 	{
745 		public SetLogOptionsAction()
746 		{
747 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
748 			putValue( Action.SHORT_DESCRIPTION, "Sets MockService Log Options" );
749 		}
750 
751 		public void actionPerformed( ActionEvent e )
752 		{
753 			String s = UISupport.prompt( "Enter maximum number of rows for MockService Log", "Log Options", String
754 					.valueOf( logListModel.getMaxSize() ) );
755 			if( s != null )
756 			{
757 				try
758 				{
759 					long newMaxSize = Long.parseLong( s );
760 					if( newMaxSize > 0 )
761 						setMaxLogSize( newMaxSize );
762 				}
763 				catch( NumberFormatException e1 )
764 				{
765 				}
766 			}
767 		}
768 	}
769 
770 	private class ClearLogAction extends AbstractAction
771 	{
772 		public ClearLogAction()
773 		{
774 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_loadtest.gif" ) );
775 			putValue( Action.SHORT_DESCRIPTION, "Clears the MockService Log" );
776 		}
777 
778 		public void actionPerformed( ActionEvent e )
779 		{
780 			logListModel.clear();
781 			if( mockRunner != null )
782 				mockRunner.clearResults();
783 		}
784 	}
785 
786 	/***
787 	 * Mouse Listener for triggering default action and showing popup for log
788 	 * list items
789 	 * 
790 	 * @author Ole.Matzura
791 	 */
792 
793 	private final class LogListMouseListener extends AbstractListMouseListener
794 	{
795 		@Override
796 		protected ActionList getActionsForRow( JList list, int row )
797 		{
798 			MockResult result = ( MockResult )logListModel.getElementAt( row );
799 			return result == null ? null : result.getActions();
800 		}
801 	}
802 
803 	private class StartScriptGroovyEditorModel extends AbstractGroovyEditorModel
804 	{
805 		public StartScriptGroovyEditorModel()
806 		{
807 			super( new String[] { "log", "context", "mockRunner" }, WsdlMockServiceDesktopPanel.this.getModelItem(), "Start" );
808 		}
809 
810 		public String getScript()
811 		{
812 			return WsdlMockServiceDesktopPanel.this.getModelItem().getStartScript();
813 		}
814 
815 		public void setScript( String text )
816 		{
817 			WsdlMockServiceDesktopPanel.this.getModelItem().setStartScript( text );
818 		}
819 
820 		@Override
821 		public Action createRunAction()
822 		{
823 			return new AbstractAction()
824 			{
825 
826 				public void actionPerformed( ActionEvent e )
827 				{
828 					try
829 					{
830 						WsdlMockRunContext context = mockRunner == null ? new WsdlMockRunContext( WsdlMockServiceDesktopPanel.this.getModelItem(), null )
831 								: mockRunner.getMockContext();
832 						WsdlMockServiceDesktopPanel.this.getModelItem().runStartScript( context, mockRunner );
833 					}
834 					catch( Exception e1 )
835 					{
836 						UISupport.showErrorMessage( e1 );
837 					}
838 				}
839 			};
840 		}
841 	}
842 
843 	private class StopScriptGroovyEditorModel extends AbstractGroovyEditorModel
844 	{
845 		public StopScriptGroovyEditorModel()
846 		{
847 			super( new String[] { "log", "context", "mockRunner" }, WsdlMockServiceDesktopPanel.this.getModelItem(), "Stop" );
848 		}
849 
850 		public String getScript()
851 		{
852 			return WsdlMockServiceDesktopPanel.this.getModelItem().getStopScript();
853 		}
854 
855 		public void setScript( String text )
856 		{
857 			WsdlMockServiceDesktopPanel.this.getModelItem().setStopScript( text );
858 		}
859 
860 		@Override
861 		public Action createRunAction()
862 		{
863 			return new AbstractAction()
864 			{
865 
866 				public void actionPerformed( ActionEvent e )
867 				{
868 					try
869 					{
870 						WsdlMockRunContext context = mockRunner == null ? new WsdlMockRunContext( WsdlMockServiceDesktopPanel.this.getModelItem(), null )
871 								: mockRunner.getMockContext();
872 						WsdlMockServiceDesktopPanel.this.getModelItem().runStopScript( context, mockRunner );
873 					}
874 					catch( Exception e1 )
875 					{
876 						UISupport.showErrorMessage( e1 );
877 					}
878 				}
879 			};
880 		}
881 	}
882 
883 	private class OnRequestScriptGroovyEditorModel extends AbstractGroovyEditorModel
884 	{
885 		public OnRequestScriptGroovyEditorModel()
886 		{
887 			super( new String[] { "log", "context", "mockRequest", "mockRunner" }, WsdlMockServiceDesktopPanel.this.getModelItem(),
888 					"OnRequest" );
889 		}
890 
891 		public String getScript()
892 		{
893 			return WsdlMockServiceDesktopPanel.this.getModelItem().getOnRequestScript();
894 		}
895 
896 		public void setScript( String text )
897 		{
898 			WsdlMockServiceDesktopPanel.this.getModelItem().setOnRequestScript( text );
899 		}
900 
901 		@Override
902 		public Action createRunAction()
903 		{
904 			return new AbstractAction()
905 			{
906 
907 				public void actionPerformed( ActionEvent e )
908 				{
909 					try
910 					{
911 						WsdlMockRunContext context = mockRunner == null ? new WsdlMockRunContext( WsdlMockServiceDesktopPanel.this.getModelItem(), null )
912 								: mockRunner.getMockContext();
913 						WsdlMockServiceDesktopPanel.this.getModelItem().runOnRequestScript( context, mockRunner, null );
914 					}
915 					catch( Exception e1 )
916 					{
917 						UISupport.showErrorMessage( e1 );
918 					}
919 				}
920 			};
921 		}
922 	}
923 
924 	private class AfterRequestScriptGroovyEditorModel extends AbstractGroovyEditorModel
925 	{
926 		public AfterRequestScriptGroovyEditorModel()
927 		{
928 			super( new String[] { "log", "context", "mockResult", "mockRunner" }, WsdlMockServiceDesktopPanel.this.getModelItem(),
929 					"AfterRequest" );
930 		}
931 
932 		public String getScript()
933 		{
934 			return WsdlMockServiceDesktopPanel.this.getModelItem().getAfterRequestScript();
935 		}
936 
937 		public void setScript( String text )
938 		{
939 			WsdlMockServiceDesktopPanel.this.getModelItem().setAfterRequestScript( text );
940 		}
941 
942 		@Override
943 		public Action createRunAction()
944 		{
945 			return new AbstractAction()
946 			{
947 
948 				public void actionPerformed( ActionEvent e )
949 				{
950 					try
951 					{
952 						WsdlMockRunContext context = mockRunner == null ? new WsdlMockRunContext( WsdlMockServiceDesktopPanel.this.getModelItem(), null )
953 								: mockRunner.getMockContext();
954 						WsdlMockServiceDesktopPanel.this.getModelItem().runAfterRequestScript( context, mockRunner, null );
955 					}
956 					catch( Exception e1 )
957 					{
958 						UISupport.showErrorMessage( e1 );
959 					}
960 				}
961 			};
962 		}
963 	}
964 }