View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.mockoperation;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.FocusEvent;
20  import java.awt.event.FocusListener;
21  import java.beans.PropertyChangeEvent;
22  import java.beans.PropertyChangeListener;
23  
24  import javax.swing.AbstractAction;
25  import javax.swing.Action;
26  import javax.swing.BorderFactory;
27  import javax.swing.Box;
28  import javax.swing.JButton;
29  import javax.swing.JComponent;
30  import javax.swing.JLabel;
31  import javax.swing.JPanel;
32  import javax.swing.JPopupMenu;
33  import javax.swing.JScrollPane;
34  import javax.swing.JSeparator;
35  import javax.swing.JSplitPane;
36  import javax.swing.JTabbedPane;
37  import javax.swing.JTable;
38  import javax.swing.JToggleButton;
39  import javax.swing.JToolBar;
40  import javax.swing.event.TableModelEvent;
41  import javax.swing.event.TableModelListener;
42  
43  import com.eviware.soapui.SoapUI;
44  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
45  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRequest;
46  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
47  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResult;
48  import com.eviware.soapui.impl.wsdl.panels.attachments.MockAttachmentPanel;
49  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.CreateEmptyMockResponseAction;
50  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.CreateFaultMockResponseAction;
51  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.OpenRequestForMockOperationAction;
52  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.RecreateMockResponseAction;
53  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.WSIValidateResponseAction;
54  import com.eviware.soapui.impl.wsdl.panels.request.StringToStringMapTableModel;
55  import com.eviware.soapui.impl.wsdl.panels.request.components.RequestMessageXmlEditor;
56  import com.eviware.soapui.impl.wsdl.panels.request.components.ResponseMessageXmlEditor;
57  import com.eviware.soapui.impl.wsdl.panels.request.components.SoapMessageXmlEditor;
58  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlDocument;
59  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.views.source.XmlSourceEditorView;
60  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
61  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditorModel;
62  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
63  import com.eviware.soapui.model.ModelItem;
64  import com.eviware.soapui.model.mock.MockRunner;
65  import com.eviware.soapui.model.settings.Settings;
66  import com.eviware.soapui.settings.UISettings;
67  import com.eviware.soapui.support.UISupport;
68  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
69  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
70  import com.eviware.soapui.support.components.JXToolBar;
71  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
72  import com.eviware.soapui.support.types.StringToStringMap;
73  import com.eviware.soapui.support.xml.JXEditTextArea;
74  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
75  import com.jgoodies.forms.builder.ButtonBarBuilder;
76  
77  /***
78   * DesktopPanel for WsdlRequests
79   * 
80   * @author Ole.Matzura
81   */
82  
83  public class AbstractWsdlMockResponseDesktopPanel<T extends ModelItem, T2 extends WsdlMockResponse> extends ModelItemDesktopPanel<T>
84  {
85  	//private final static Log log = LogFactory.getLog(WsdlMockOperationDesktopPanel.class);
86  	private JEditorStatusBarWithProgress statusBar;
87  	private JButton splitButton;
88  	private MockRunner mockRunner;
89  	private JButton recreateButton;
90  	private JButton createEmptyButton;
91  	private JSplitPane requestSplitPane;
92  	private MoveFocusAction moveFocusAction;
93  	private ClosePanelAction closePanelAction = new ClosePanelAction();
94  	private RunScriptAction runScriptAction = new RunScriptAction();
95  
96  	private SoapMessageXmlEditor requestEditor;
97  	private SoapMessageXmlEditor responseEditor;
98  
99  	public WSIValidateResponseAction wsiValidateAction;
100 
101 	private JTabbedPane requestTabs;
102 	private JPanel requestTabPanel;
103 	private JToggleButton tabsButton;
104 
105 	public boolean responseHasFocus;
106 
107 	private JTabbedPane requestEditorTabs;
108 	private JTabbedPane responseEditorTabs;
109 
110 	private JPanel requestEditorTabPanel;
111 	private JPanel responseEditorTabPanel;
112 	private InternalPropertyChangeListener propertyChangeListener = new InternalPropertyChangeListener();
113 	private StringToStringMapTableModel responseHeadersModel;
114 	private JTable responseHeadersTable;
115 	private StringToStringMapTableModel requestHeadersModel;
116 	private GroovyEditor responseScriptEditor;
117 	private JButton createFaultButton;
118 	private T2 mockResponse;
119 	private JButton openRequestButton;;
120 
121 	public AbstractWsdlMockResponseDesktopPanel(T modelItem)
122 	{
123 		super(modelItem);
124 	}
125 	
126 	protected void init( T2 mockResponse )
127 	{
128 		this.mockResponse = mockResponse;
129 		
130 		add(buildContent(), BorderLayout.CENTER);
131 		add(buildToolbar(), BorderLayout.NORTH);
132 		add(buildStatusLabel(), BorderLayout.SOUTH);
133 
134 		setPreferredSize(new Dimension(600, 500));
135 		
136 		mockResponse.addPropertyChangeListener( propertyChangeListener );
137 	}
138 
139 	protected WsdlMockResponse getMockResponse()
140 	{
141 		return mockResponse;
142 	}
143 
144 	public final SoapMessageXmlEditor getRequestEditor()
145 	{
146 		return requestEditor;
147 	}
148 
149 	public final SoapMessageXmlEditor getResponseEditor()
150 	{
151 		return responseEditor;
152 	}
153 	
154 	public MockRunner getSubmit()
155 	{
156 		return mockRunner;
157 	}
158 
159 	protected JComponent buildStatusLabel()
160 	{
161 		statusBar = new JEditorStatusBarWithProgress();
162 		statusBar.setBorder( BorderFactory.createEmptyBorder( 1, 0, 0, 0 ));
163 		
164 		return statusBar;
165 	}
166 
167 	public JEditorStatusBarWithProgress getStatusBar()
168 	{
169 		return statusBar;
170 	}
171 
172 	protected JComponent buildContent()
173 	{
174 		requestSplitPane = UISupport.createHorizontalSplit();
175 		requestSplitPane.setResizeWeight(0.5);
176 		requestSplitPane.setBorder(null);
177 		
178 		splitButton = createActionButton(new ChangeSplitPaneOrientationAction(requestSplitPane), true);
179 		
180 		tabsButton = new JToggleButton( new ChangeToTabsAction() );
181 		tabsButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
182 		
183 		openRequestButton = createActionButton(new OpenRequestForMockOperationAction( mockResponse.getMockOperation() ), true);
184 		recreateButton = createActionButton(new RecreateMockResponseAction( mockResponse ), true);
185 		createEmptyButton = createActionButton(new CreateEmptyMockResponseAction(mockResponse), true);
186 		createFaultButton = createActionButton(new CreateFaultMockResponseAction(mockResponse), true);
187 
188 		moveFocusAction = new MoveFocusAction();
189 		wsiValidateAction = new WSIValidateResponseAction( mockResponse );
190 
191 		requestEditor = buildRequestEditor();
192 		responseEditor = buildResponseEditor();
193 		JComponent scriptEditor = buildResponseScriptEditor();
194 		
195 		WsdlMockResult mockResult = mockResponse.getMockResult();
196 		int requestHeadersSize = mockResult == null ? -1 : mockResult.getMockRequest().getRequestHeaders().size();
197 		int requestAttachmentsSize = mockResult == null ? -1 : mockResult.getMockRequest().getRequestAttachments().length;
198 		
199 		requestEditorTabs = new JTabbedPane( JTabbedPane.BOTTOM );
200 		requestEditorTabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
201 		requestEditorTabs.addTab( "SOAP Request", requestEditor );
202 		requestEditorTabs.addTab( "Request Attachments (" + (requestAttachmentsSize == -1 ? "-" : requestAttachmentsSize) + ")", 
203 					new MockAttachmentPanel( mockResponse, false ));
204 		requestEditorTabs.addTab( "HTTP Headers (" + (requestHeadersSize == -1 ? "-" : requestHeadersSize ) + ")", 
205 					createRequestHttpHeadersPanel() );
206 		
207 		responseEditorTabs = new JTabbedPane( JTabbedPane.BOTTOM );
208 		responseEditorTabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
209 		responseEditorTabs.addTab( "Mock Response", responseEditor );
210 		responseEditorTabs.addTab( "Response Script", scriptEditor );
211 		responseEditorTabs.addTab( "Response Attachments (" + 
212 					mockResponse.getAttachments().length + ")", new MockAttachmentPanel( mockResponse, true ));
213 		responseEditorTabs.addTab(  "Response HTTP Headers", createResponseHttpHeadersPanel() );
214 		responseEditorTabs.setTitleAt( 3, "Response HTTP Headers (" + responseHeadersModel.getRowCount() + ")");
215 		
216 		requestTabs = new JTabbedPane();
217 	   requestTabPanel = UISupport.createTabPanel( requestTabs, true );
218 	   
219 	   requestEditorTabPanel = UISupport.createTabPanel(requestEditorTabs, false);
220 		responseEditorTabPanel = UISupport.createTabPanel(responseEditorTabs, false);
221 		
222 		JComponent component = null;
223 		
224 		if( mockResponse.getSettings().getBoolean( UISettings.START_WITH_REQUEST_TABS ))
225 	   {
226 	   	requestTabs.addTab( "Last Request", requestEditorTabPanel );
227 	   	requestTabs.addTab( "Mock Response", responseEditorTabPanel );
228 	   	splitButton.setEnabled( false );
229 	   	tabsButton.setSelected( true );
230 	   	component = requestTabPanel;
231 	   	
232 	   	requestTabs.setSelectedIndex( 1 );
233 	   }
234 	   else
235 	   {
236 	   	requestSplitPane.setTopComponent(requestEditorTabPanel);
237 	   	requestSplitPane.setBottomComponent(responseEditorTabPanel);
238 	   	requestSplitPane.setDividerLocation(0.5);
239 	   	component = requestSplitPane;
240 	   }
241 		
242 		return component;
243 	}
244 
245 	private Component createRequestHttpHeadersPanel()
246 	{
247 		requestHeadersModel = new StringToStringMapTableModel( new StringToStringMap(), "Header", "Value", false );
248 		requestHeadersModel.addTableModelListener( new TableModelListener() 
249 		{
250 			public void tableChanged( TableModelEvent arg0 )
251 			{
252 				requestEditorTabs.setTitleAt( 2, "HTTP Headers (" + requestHeadersModel.getRowCount() + ")");
253 			}} );
254 		
255 		JTable requestHeadersTable = new JTable( requestHeadersModel );
256 		return new JScrollPane( requestHeadersTable );
257 	}
258 
259 	private Component createResponseHttpHeadersPanel()
260 	{
261 		responseHeadersModel = new StringToStringMapTableModel( mockResponse.getResponseHeaders(), 
262 					"Header", "Value", true );
263 		responseHeadersModel.addTableModelListener( new TableModelListener() 
264 		{
265 			public void tableChanged( TableModelEvent arg0 )
266 			{
267 				mockResponse.setResponseHeaders( responseHeadersModel.getData() );
268 				responseEditorTabs.setTitleAt( 3, "Response HTTP Headers (" + responseHeadersModel.getRowCount() + ")");
269 			}} );
270 		
271 		responseHeadersTable = new JTable( responseHeadersModel );
272 		JPanel panel = new JPanel( new BorderLayout() );
273 
274 		panel.add( new JScrollPane( responseHeadersTable ), BorderLayout.CENTER );
275 		
276 		ButtonBarBuilder builder = new ButtonBarBuilder();
277 		builder.addFixed( new JButton( new AbstractAction( "Add" ) {
278 
279 			public void actionPerformed( ActionEvent arg0 )
280 			{
281 				Object header = UISupport.prompt( "Specify name of header to add", "Add HTTP Header", "" );
282 				if( header != null )
283 				{
284 					responseHeadersModel.add( header.toString(), "" );
285 				}
286 			}} ));
287 		builder.addRelatedGap();
288 		builder.addFixed( new JButton( new AbstractAction("Remove" ){
289 
290 			public void actionPerformed( ActionEvent arg0 )
291 			{
292 				int row = responseHeadersTable.getSelectedRow();
293 				if( row != -1 && UISupport.confirm( "Delete selected header?", "Remove Header" ) )
294 				{
295 					responseHeadersModel.remove( row );
296 				}
297 			}} ));
298 		
299 		
300 		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
301 		panel.add( builder.getPanel(), BorderLayout.SOUTH );
302 		
303 		return panel;
304 	}
305 	
306 	protected JComponent buildResponseScriptEditor()
307 	{
308 		responseScriptEditor = new GroovyEditor( new MockResponseGroovyEditorModel() );
309 		
310 		JPanel panel = new JPanel( new BorderLayout() );
311 		panel.add( buildScriptToolbar(), BorderLayout.NORTH );
312 		panel.add( new JScrollPane( responseScriptEditor ), BorderLayout.CENTER );
313 		return panel;
314 	}
315 	
316 	private JComponent buildScriptToolbar()
317 	{
318 		JXToolBar toolBar = UISupport.createToolbar();
319 		JButton runButton = UISupport.createToolbarButton( runScriptAction );
320 		toolBar.add( runButton );
321 		toolBar.add( Box.createHorizontalGlue() );
322 		JLabel label = new JLabel("<html>Script is invoked with <code>log</code>, <code>context</code>, <code>mockRequest</code>" +
323 				" and <code>mockResponse</code> variables</html>");
324 		label.setToolTipText( label.getText() );
325 		label.setMaximumSize( label.getPreferredSize() );
326 		
327 		toolBar.add( label);
328 		toolBar.addUnrelatedGap();
329 		toolBar.addFixed( createActionButton( new ShowOnlineHelpAction( HelpUrls.MOCKRESPONSE_SCRIPT_HELP_URL ), true ));
330 		
331 		return toolBar;
332 	}
333 
334 	protected SoapMessageXmlEditor buildResponseEditor()
335 	{
336 		return new ResponseMessageEditor( new MockResponseXmlDocument( mockResponse ));
337 	}
338 
339 	protected SoapMessageXmlEditor buildRequestEditor()
340 	{
341 		return new RequestMessageEditor( new MockRequestXmlDocument( mockResponse ));
342 	}
343 
344 	protected JComponent buildToolbar()
345 	{
346 		JXToolBar toolbar =  UISupport.createToolbar(); 
347 		
348 		toolbar.add( openRequestButton);
349 		toolbar.addUnrelatedGap();
350 		toolbar.add(recreateButton);
351 		toolbar.add(createEmptyButton);
352 		toolbar.add(createFaultButton);
353 		
354 		createToolbar( toolbar );
355 		
356 		toolbar.add( Box.createHorizontalGlue() );
357 		toolbar.add( tabsButton );
358 		toolbar.add(splitButton);
359 		toolbar.add(UISupport.createToolbarButton(new ShowOnlineHelpAction(getHelpUrl())));
360 		
361 		return toolbar;
362 	}
363 
364 	protected void createToolbar( JXToolBar toolbar )
365 	{
366 	}
367 
368 	protected String getHelpUrl()
369 	{
370 		return HelpUrls.REQUESTEDITOR_HELP_URL;
371 	}
372 
373 	protected void insertButtons(JToolBar toolbar)
374 	{
375 	}
376 
377 	public void setEnabled(boolean enabled)
378 	{
379 		requestEditor.getSourceEditor().setEditable(enabled);
380 		responseEditor.getSourceEditor().setEditable(enabled);
381 		recreateButton.setEnabled(enabled);
382 		createEmptyButton.setEnabled(enabled);
383 		
384 		
385 		statusBar.setIndeterminate( !enabled );
386 	}
387 
388 	private final class InternalPropertyChangeListener implements PropertyChangeListener
389 	{
390 		public void propertyChange(PropertyChangeEvent evt)
391 		{
392 			if( evt.getPropertyName().equals( WsdlMockResponse.MOCKRESULT_PROPERTY ))
393 			{
394 				WsdlMockRequest mockRequest = mockResponse.getMockResult().getMockRequest();
395 				requestEditor.getXmlDocument().setXml( mockRequest == null ? "" : mockRequest.getRequestContent());
396 				
397 				// update headers
398 				requestHeadersModel.setData( mockRequest.getRequestHeaders() );
399 				requestEditorTabs.setTitleAt( 2, "HTTP Headers (" + (mockRequest == null ? "-" : mockRequest.getRequestHeaders().size() + ")") );
400 				
401 				// update attachments
402 				requestEditorTabs.setTitleAt( 1, "Request Attachments (" + (mockRequest == null ? 0 :
403 					mockRequest.getRequestAttachments().length) + ")" );
404 				
405 				wsiValidateAction.setEnabled( true );
406 			}
407 		}
408 	}
409 
410 	public class RequestMessageEditor extends RequestMessageXmlEditor<WsdlMockResponse>
411 	{
412 		public RequestMessageEditor(XmlDocument document)
413 		{
414 			super(document, mockResponse);
415 		}
416 
417 		protected XmlSourceEditorView buildSourceEditor()
418 		{
419 			XmlSourceEditorView editor = getSourceEditor();
420 			JXEditTextArea inputArea = editor.getInputArea();
421 
422 			inputArea.addFocusListener(new InputAreaFocusListener());
423 			
424 			inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
425 			inputArea.getInputHandler().addKeyBinding("F5", recreateButton.getAction());
426 			inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
427 
428 			return editor;
429 		}
430 	}
431 	
432 	
433 
434 	public class ResponseMessageEditor extends ResponseMessageXmlEditor<WsdlMockResponse>
435 	{
436 		public ResponseMessageEditor(XmlDocument document)
437 		{
438 			super(document, mockResponse );
439 		}
440 
441 		protected XmlSourceEditorView buildSourceEditor()
442 		{
443 			XmlSourceEditorView editor = getSourceEditor();
444 			
445 			JXEditTextArea inputArea = editor.getInputArea();
446 			inputArea.addFocusListener(new ResultAreaFocusListener());
447 			
448 			inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
449 			inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
450 			
451 			JPopupMenu inputPopup = editor.getEditorPopup();
452 			inputPopup.insert( new JSeparator(), 2 );
453 			inputPopup.insert( wsiValidateAction, 3 );
454 			
455 			return editor;
456 		}
457 	}
458 	
459 	protected final class InputAreaFocusListener implements FocusListener
460 	{
461 		public void focusGained(FocusEvent e)
462 		{
463 			responseHasFocus = false;
464 			
465 			statusBar.setTarget( requestEditor.getSourceEditor().getInputArea() );
466 			if( !splitButton.isEnabled() )
467 			{
468 				requestTabs.setSelectedIndex( 0 );
469 				return;
470 			}
471 			
472 			if (getModelItem().getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
473 				return;
474 
475 			// dont resize if split has been dragged
476 			if (((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged())
477 				return;
478 
479 			int pos = requestSplitPane.getDividerLocation();
480 			if (pos >= 600)
481 				return;
482 			if (requestSplitPane.getMaximumDividerLocation() > 700)
483 				requestSplitPane.setDividerLocation(600);
484 			else
485 				requestSplitPane.setDividerLocation(0.8);
486 		}
487 
488 		public void focusLost(FocusEvent e)
489 		{
490 		}
491 	}
492 
493 	protected final class ResultAreaFocusListener implements FocusListener
494 	{
495 		public void focusGained(FocusEvent e)
496 		{
497 			responseHasFocus = true;
498 			
499 			statusBar.setTarget( responseEditor.getSourceEditor().getInputArea() );
500 			if( !splitButton.isEnabled() )
501 			{
502 				requestTabs.setSelectedIndex( 1 );
503 				return;
504 			}
505 			
506 			if (getModelItem().getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
507 				return;
508 
509 			// dont resize if split has been dragged or result is empty
510 			if (((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged() )
511 				return;
512 
513 			int pos = requestSplitPane.getDividerLocation();
514 			int maximumDividerLocation = requestSplitPane.getMaximumDividerLocation();
515 			if (pos + 600 < maximumDividerLocation)
516 				return;
517 
518 			if (maximumDividerLocation > 700)
519 				requestSplitPane.setDividerLocation(maximumDividerLocation - 600);
520 			else
521 				requestSplitPane.setDividerLocation(0.2);
522 		}
523 
524 		public void focusLost(FocusEvent e)
525 		{
526 		}
527 	}
528 
529 	private class ClosePanelAction extends AbstractAction
530 	{
531 		public void actionPerformed(ActionEvent e)
532 		{
533 			SoapUI.getDesktop().closeDesktopPanel(getModelItem());
534 		}
535 	}
536 
537 	private class MoveFocusAction extends AbstractAction
538 	{
539 		public void actionPerformed(ActionEvent e)
540 		{
541 			if (requestEditor.hasFocus())
542 			{
543 				responseEditor.requestFocus();
544 			}
545 			else
546 			{
547 				requestEditor.requestFocus();
548 			}
549 		}
550 	}
551 
552 	public boolean dependsOn(ModelItem modelItem)
553 	{
554 		return modelItem == getModelItem() || modelItem == mockResponse.getMockOperation()
555 				|| modelItem == mockResponse.getMockOperation().getMockService()
556 				|| modelItem == mockResponse.getMockOperation().getMockService().getProject();
557 	}
558 
559 	public String getDescription()
560 	{
561 		return "MockResponse: [" + getModelItem().getName() + "] for " + mockResponse.getMockOperation().getName();
562 	}
563 	
564 	private final class ChangeToTabsAction extends AbstractAction
565 	{
566 		public ChangeToTabsAction()
567 		{
568 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/toggle_tabs.gif"));
569 			putValue(Action.SHORT_DESCRIPTION, "Toggles to tab-based layout");
570 		}
571 		
572 		public void actionPerformed(ActionEvent e)
573 		{
574 			if( splitButton.isEnabled() )
575 			{
576 				splitButton.setEnabled( false );
577 				removeContent( requestSplitPane );
578 				setContent( requestTabPanel );
579 				requestTabs.addTab( "Last Request", requestEditorTabPanel );
580 				requestTabs.addTab( "Mock Response", responseEditorTabPanel );
581 				
582 				if( responseHasFocus )
583 				{
584 					requestTabs.setSelectedIndex( 1 );
585 					requestEditorTabs.requestFocus();
586 				}
587 				else
588 				{
589 					responseEditorTabs.requestFocus();
590 				}
591 			}
592 			else
593 			{
594 				int selectedIndex = requestTabs.getSelectedIndex();
595 				
596 				splitButton.setEnabled( true );
597 				removeContent( requestTabPanel );
598 				setContent( requestSplitPane );
599 				requestSplitPane.setTopComponent(requestEditorTabPanel);
600 		   	requestSplitPane.setBottomComponent(responseEditorTabPanel);
601 		   	requestSplitPane.setDividerLocation(0.5);
602 		   	
603 		   	if( selectedIndex == 0 )
604 		   		requestEditor.requestFocus();
605 		   	else
606 		   		responseEditor.requestFocus();
607 			}
608 			
609 			revalidate();
610 		}
611 	}
612 
613 	public void setContent(JComponent content)
614 	{
615 		add( content, BorderLayout.CENTER );
616 	}
617 
618 	public void removeContent(JComponent content)
619 	{
620 		remove( content );
621 	}
622 	
623 	public boolean onClose( boolean canCancel )
624 	{
625 		return release();
626 	}
627 	
628 	private class RunScriptAction extends AbstractAction
629 	{
630 		public RunScriptAction()
631 		{
632 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ));
633 			putValue( Action.SHORT_DESCRIPTION, "Runs this script using mock httpRequest/httpResponse objects" );
634 		}
635 
636 		public void actionPerformed(ActionEvent e)
637 		{
638 			try
639 			{
640 				mockResponse.evaluateScript( mockResponse.getMockResult() == null ? null :
641 					mockResponse.getMockResult().getMockRequest() );
642 				
643 				StringToStringMap values = null;
644 				if( mockResponse.getMockResult() != null ) 
645 					values = mockResponse.getMockResult().getMockRequest().getContext().toStringToStringMap();
646 					
647 				if( values == null || values.isEmpty() )
648 				{
649 					UISupport.showInfoMessage( "No values were returned" );
650 				}
651 				else
652 				{
653 					String msg = "<html><body>Returned values:<br>";
654 					
655 					for( String name : values.keySet() )
656 					{
657 						msg += name + " : " + values.get( name ) + "<br>";
658 					}
659 					
660 					msg +="</body></html>";
661 					
662 					UISupport.showInfoMessage( msg );
663 				}
664 			}
665 			catch( RuntimeException e1 )
666 			{
667 				responseScriptEditor.selectError( e1.getMessage() );
668 				UISupport.showErrorMessage( e1 );
669 			}
670 		}
671 	}
672 	
673 	private class MockResponseGroovyEditorModel implements GroovyEditorModel
674 	{
675 		public String[] getKeywords()
676 		{
677 			return new String[] {"context", "mockRequest", "mockResponse" };
678 		}
679 
680 		public Action getRunAction()
681 		{
682 			return runScriptAction;
683 		}
684 
685 		public String getScript()
686 		{
687 			return mockResponse.getScript();
688 		}
689 
690 		public void setScript( String text )
691 		{
692 			mockResponse.setScript( text );
693 		}
694 
695 		public Settings getSettings()
696 		{
697 			return SoapUI.getSettings();
698 		}}
699 }