View Javadoc

1   /*
2    *  soapui, copyright (C) 2005 Ole Matzura / 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.request;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.Toolkit;
19  import java.awt.event.ActionEvent;
20  import java.awt.event.FocusEvent;
21  import java.awt.event.FocusListener;
22  import java.awt.event.ItemEvent;
23  import java.awt.event.ItemListener;
24  import java.awt.event.KeyEvent;
25  import java.awt.event.MouseAdapter;
26  import java.awt.event.MouseEvent;
27  import java.beans.PropertyChangeEvent;
28  import java.beans.PropertyChangeListener;
29  import java.text.SimpleDateFormat;
30  import java.util.ArrayList;
31  import java.util.Date;
32  import java.util.List;
33  
34  import javax.swing.AbstractAction;
35  import javax.swing.AbstractListModel;
36  import javax.swing.Action;
37  import javax.swing.BorderFactory;
38  import javax.swing.DefaultListModel;
39  import javax.swing.JButton;
40  import javax.swing.JComboBox;
41  import javax.swing.JComponent;
42  import javax.swing.JLabel;
43  import javax.swing.JList;
44  import javax.swing.JOptionPane;
45  import javax.swing.JPanel;
46  import javax.swing.JPopupMenu;
47  import javax.swing.JScrollPane;
48  import javax.swing.JSplitPane;
49  import javax.swing.JTabbedPane;
50  import javax.swing.JTextArea;
51  import javax.swing.KeyStroke;
52  import javax.swing.ListCellRenderer;
53  import javax.swing.event.DocumentEvent;
54  import javax.swing.event.DocumentListener;
55  import javax.swing.event.PopupMenuEvent;
56  import javax.swing.event.PopupMenuListener;
57  
58  import org.apache.commons.logging.Log;
59  import org.apache.commons.logging.LogFactory;
60  
61  import com.eviware.soapui.SoapUI;
62  import com.eviware.soapui.impl.wsdl.WsdlRequest;
63  import com.eviware.soapui.impl.wsdl.actions.request.CreateEmptyRequestAction;
64  import com.eviware.soapui.impl.wsdl.actions.request.RecreateRequestAction;
65  import com.eviware.soapui.impl.wsdl.panels.request.actions.ValidateRequestXmlAction;
66  import com.eviware.soapui.impl.wsdl.panels.request.actions.ValidateResponseXmlAction;
67  import com.eviware.soapui.impl.wsdl.panels.request.support.EndpointsComboBoxModel;
68  import com.eviware.soapui.impl.wsdl.teststeps.WsdlAssertion;
69  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequest;
70  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
71  import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
72  import com.eviware.soapui.impl.wsdl.teststeps.actions.CloneTestRequestStepAction;
73  import com.eviware.soapui.impl.wsdl.teststeps.assertions.AssertionError;
74  import com.eviware.soapui.model.DesktopPanel;
75  import com.eviware.soapui.model.ModelItem;
76  import com.eviware.soapui.model.iface.Submit;
77  import com.eviware.soapui.model.iface.SubmitListener;
78  import com.eviware.soapui.model.iface.Submit.Status;
79  import com.eviware.soapui.support.JXmlTextArea;
80  import com.eviware.soapui.support.SoapUISplitPaneUI;
81  import com.eviware.soapui.support.UISupport;
82  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
83  import com.eviware.soapui.support.actions.FormatXmlAction;
84  import com.eviware.soapui.support.actions.SaveXmlTextAreaAction;
85  import com.jgoodies.forms.builder.ButtonBarBuilder;
86  
87  /***
88   * DesktopPanel for WsdlTestRequest. Essentially a copy of WsdlRequestDesktopPanel with assertions.
89   * 
90   * @author Ole.Matzura
91   */
92  
93  public class WsdlTestRequestDesktopPanel extends JPanel implements DesktopPanel
94  {
95     private JXmlTextArea resultArea;
96     private JXmlTextArea inputArea;
97     private JComboBox endpointCombo;
98     private JButton submitButton;
99     private JButton recreateButton;
100    private JButton cancelButton;
101    private JComboBox encodingCombo;
102    private WsdlTestRequest request;
103    private EndpointsComboBoxModel endpointsModel;
104    
105    private final static Log log = LogFactory.getLog( WsdlTestRequestDesktopPanel.class );
106    private JTextArea logArea;
107    private JButton createEmptyButton;
108    private JList assertionList;
109    private JLabel statusLabel;
110    private JPopupMenu assertionListPopup;
111    private AssertionListModel assertionListModel;
112    private InternalPropertyChangeListener internalPropertyChangeListener;
113    private JButton cloneButton;
114    private JButton splitButton;
115    private WsdlTestRequestStep requestStep;
116 	public Submit submit;
117 	private InternalSubmitListener internalSubmitListener;
118 	private JSplitPane requestSplitPane;
119 	private MoveFocusAction moveFocusAction;
120 	private JButton addAssertionButton;
121 
122    public WsdlTestRequestDesktopPanel( WsdlTestRequestStep requestStep )
123    {
124       super( new BorderLayout() );
125       this.requestStep = requestStep;
126       this.request = requestStep.getTestRequest();
127       this.endpointsModel = new EndpointsComboBoxModel( request );
128 
129       internalSubmitListener = new InternalSubmitListener();
130 		request.addSubmitListener( internalSubmitListener );
131       
132       internalPropertyChangeListener = new InternalPropertyChangeListener();
133       request.addPropertyChangeListener( internalPropertyChangeListener );
134       request.getOperation().getInterface().addPropertyChangeListener( internalPropertyChangeListener ); 
135       
136       add( buildUI(), BorderLayout.CENTER );
137       add( buildSearchBar(), BorderLayout.NORTH );
138       
139       statusLabel = new JLabel();
140       add( statusLabel, BorderLayout.PAGE_END );
141       
142       setPreferredSize( new Dimension( 600, 500 ));
143    }
144 
145    private Component buildLogPanel()
146    {
147       JTabbedPane tabbedPane = new JTabbedPane( JTabbedPane.BOTTOM );
148       
149       logArea = new JTextArea();
150       logArea.setEditable(false);
151       logArea.setToolTipText("Request Log");
152       
153       JPanel panel = new JPanel(new BorderLayout());
154       panel.add(new JScrollPane(logArea), BorderLayout.CENTER);
155       
156       tabbedPane.addTab( "Assertions", buildAssertionsPanel() );
157       tabbedPane.addTab( "Request Log", panel );
158       return tabbedPane;
159    }
160    
161    private Component buildAssertionsPanel()
162    {
163       assertionListModel = new AssertionListModel();
164       assertionList = new JList( assertionListModel );
165       assertionList.setToolTipText( "Assertions for this request" );
166       assertionList.setCellRenderer( new AssertionCellRenderer() );
167       
168       assertionListPopup = new JPopupMenu();
169       assertionListPopup.add( new AddAssertionAction( requestStep.getTestRequest() ));
170       
171       assertionListPopup.addPopupMenuListener( new PopupMenuListener(){
172 
173          public void popupMenuWillBecomeVisible(PopupMenuEvent e)
174          {
175             while( assertionListPopup.getComponentCount() > 1 ) 
176                assertionListPopup.remove( 1 );
177             
178             if( assertionListModel.getSize() == 0 ) return;
179             int ix = assertionList.getSelectedIndex();
180             if( ix == -1 ) return;
181             
182             WsdlAssertion assertion = assertionListModel.getAssertionAt( ix );
183             Action[] actions = assertion.getActions();
184             
185             for (int i = 0; i < actions.length; i++)
186             {
187                assertionListPopup.add( actions[i] );
188             }
189          }
190 
191          public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
192          {
193          }
194 
195          public void popupMenuCanceled(PopupMenuEvent e)
196          {
197          }});
198       
199       assertionList.setComponentPopupMenu( assertionListPopup );
200       
201       assertionList.addMouseListener( new MouseAdapter() {
202 
203 			public void mouseClicked(MouseEvent e)
204          {
205          	
206             if( e.getClickCount() < 2 ) return;
207 
208             int ix = assertionList.getSelectedIndex();
209             if( ix == -1 ) return;
210             
211             Object obj = assertionList.getModel().getElementAt( ix );
212             if( obj instanceof WsdlAssertion )
213             {
214 	            WsdlAssertion assertion = (WsdlAssertion) obj;
215 	            if( assertion.isConfigurable() )
216 	               assertion.configure();
217             }
218    		   if( obj instanceof AssertionError )
219    		   {
220    		   	AssertionError error = (AssertionError) obj;
221    		   	if( error.getLineNumber() >= 0 )
222    		   	{
223    		   		resultArea.setCaretPosition( resultArea.getLineStartOffset( error.getLineNumber()-1 ) );
224    		   		resultArea.requestFocus();
225    		   	}
226    		   	else Toolkit.getDefaultToolkit().beep();
227    		   }
228    		   else Toolkit.getDefaultToolkit().beep();
229          }});
230       
231       return new JScrollPane( assertionList );
232    }
233 
234    class AssertionCellRenderer extends JLabel implements ListCellRenderer 
235    {
236       public Component getListCellRendererComponent(
237         JList list,
238         Object value,           
239         int index,               
240         boolean isSelected,      
241         boolean cellHasFocus)    
242       {
243       	if( value instanceof WsdlAssertion )
244       	{
245       		WsdlAssertion assertion = (WsdlAssertion) value;
246       		setText( assertion.getName() + " - " + assertion.getStatus().toString() );
247             setIcon( assertion.getIcon() );
248       	}
249       	else if( value instanceof AssertionError )
250       	{
251             AssertionError assertion = (AssertionError) value;
252             setText( " -> " + assertion.toString() );
253             setIcon( null );
254       	}
255       	
256           if (isSelected) 
257           {
258              setBackground(list.getSelectionBackground());
259              setForeground(list.getSelectionForeground());
260           }
261           else 
262           {
263              setBackground(list.getBackground());
264              setForeground(list.getForeground());
265           }
266           
267           setEnabled(list.isEnabled());
268           setFont(list.getFont());
269           setOpaque(true);
270           
271           return this;
272       }
273   }
274    
275    private class AssertionListModel extends AbstractListModel implements PropertyChangeListener, 
276        WsdlTestRequest.WsdlTestRequestListener
277    {
278    	private List<Object> items = new ArrayList<Object>();
279    	
280       public AssertionListModel()
281       {
282       	init();
283       }
284       
285       public int getSize()
286       {
287       	return items.size();
288       }
289 
290       public Object getElementAt(int index)
291       {
292       	return items.get( index );
293       }
294 
295       public WsdlAssertion getAssertionAt( int index )
296       {
297       	Object object = items.get( index );
298       	while( object instanceof AssertionError && index > 0 )
299       	{
300       		object = items.get( --index );
301       	}
302       	
303       	return (WsdlAssertion) object;
304       }
305       
306       public void refresh()
307       {
308 			release();
309       	init();
310          fireContentsChanged( this, 0, getSize() );
311       }
312 
313 		private void init()
314 		{
315       	request.addWsdlTestRequestListener( this );
316 			
317          for( int c = 0; c < request.getAssertionCount(); c++ )
318          {
319          	WsdlAssertion assertion = request.getAssertionAt( c );
320          	addAssertion(assertion);
321          }
322 		}
323 		
324 		public void release()
325 		{
326          items.clear();
327 
328          for( int c = 0; c < request.getAssertionCount(); c++ )
329          {
330          	WsdlAssertion assertion = request.getAssertionAt( c );
331          	assertion.removePropertyChangeListener( this );
332          }
333          
334          request.removeWsdlTestRequestListener( this );
335 		}
336 
337 		public void propertyChange(PropertyChangeEvent evt)
338 		{
339 			refresh();
340 		}
341 
342 		public void assertionAdded(WsdlAssertion assertion)
343 		{
344 			int sz = getSize();
345       	addAssertion(assertion);
346       	
347       	fireIntervalAdded( this, sz, items.size()-1 );
348 		}
349 
350 		private void addAssertion(WsdlAssertion assertion)
351 		{
352 			assertion.addPropertyChangeListener( this );
353       	items.add( assertion );
354       	
355       	AssertionError[] errors = assertion.getErrors();
356       	if( errors != null)
357       	{
358       		for( int i = 0; i < errors.length; i++ )
359       		items.add( errors[i] );
360       	}
361 		}
362 
363 		public void assertionRemoved(WsdlAssertion assertion)
364 		{
365 			int ix = items.indexOf( assertion );
366 			if( ix == -1 ) return;
367 
368 			assertion.removePropertyChangeListener( this );
369 			items.remove( ix );
370 			fireIntervalRemoved( this, ix, ix );
371 			
372 			// remove associated errors
373 			while( ix < items.size() && items.get( ix ) instanceof AssertionError )
374 			{
375 				items.remove( ix );
376 				fireIntervalRemoved( this, ix, ix );
377 			}
378 		}
379    }
380    
381    private JComponent buildUI()
382    {
383    	requestSplitPane = UISupport.createHorizontalSplit();
384 		submitButton = createActionButton( new SubmitAction(), true );
385       cancelButton = createActionButton( new CancelAction(), false );
386       addAssertionButton = createActionButton( new AddAssertionAction( request ), true );
387       splitButton = createActionButton( new ChangeSplitPaneOrientationAction( requestSplitPane ), true );
388       recreateButton = createActionButton( new RecreateRequestAction(request), true );
389       cloneButton = createActionButton( new CloneTestRequestStepAction( requestStep ), true );
390       createEmptyButton = createActionButton( new CreateEmptyRequestAction(request), true );
391       
392       submitButton.setEnabled( request.getEndpoint() != null && request.getEndpoint().trim().length() > 0 );
393       moveFocusAction = new MoveFocusAction();
394       
395       requestSplitPane.setTopComponent( buildInputUI() );
396       requestSplitPane.setBottomComponent( buildOutputUI() );
397       requestSplitPane.setDividerLocation( 0.5 );
398       requestSplitPane.setResizeWeight( 0.5 );
399       requestSplitPane.setBorder( null );
400       
401       JSplitPane outerSplit = UISupport.createVerticalSplit();
402       outerSplit.setTopComponent( requestSplitPane );
403       outerSplit.setBottomComponent( buildLogPanel() );
404       outerSplit.setDividerLocation( 350 );
405       outerSplit.setResizeWeight( 0.9 );
406       outerSplit.setBorder( null );
407 
408       return outerSplit;
409    }
410    
411    private JButton createActionButton( Action action, boolean enabled )
412    {
413    	JButton button = new JButton( action );
414    	action.putValue( Action.NAME, null );
415    	button.setPreferredSize( new Dimension(24, 24 ));
416    	button.setEnabled( enabled );
417    	return button;
418    }
419 
420    private Component buildOutputUI()
421    {
422    	resultArea = new JXmlTextArea();
423       resultArea.setMinimumSize( new Dimension( 50, 50 ));
424       resultArea.setToolTipText( "Response Area" );
425       if( request.getResponseContent() != null )
426       {
427    		resultArea.setText( request.getResponseContent() );
428    		resultArea.setCaretPosition( 0 );
429       }
430       resultArea.addFocusListener( new ResultAreaFocusListener() );
431       
432       DefaultListModel listModel = new DefaultListModel();
433       JList list = new JList( listModel );
434       list.setToolTipText( "Response Validation Errors" );
435       list.addMouseListener( new ValidationListMouseAdapter( list, resultArea ));
436 		JScrollPane scrollPane = new JScrollPane( list );
437 		scrollPane.setVisible( false );
438 		
439 		JSplitPane resultAreaSplit = UISupport.createVerticalSplit();
440 
441 		JPopupMenu popup = new JPopupMenu();
442       ValidateResponseXmlAction validateResponseXmlAction = new ValidateResponseXmlAction( request, scrollPane, listModel, resultAreaSplit, resultArea );
443       popup.add( validateResponseXmlAction );
444       FormatXmlAction formatXmlAction = new FormatXmlAction(resultArea);
445 		popup.add( formatXmlAction);
446       popup.addSeparator();
447       popup.add( resultArea.getUndoAction() );
448       popup.add( resultArea.getRedoAction() );
449       popup.add( resultArea.getCopyAction() );
450       popup.add( resultArea.getCutAction() );
451       popup.add( resultArea.getPasteAction() );
452       popup.addSeparator();
453       popup.add( resultArea.getFindAndReplaceAction() );
454       popup.addSeparator();
455       SaveXmlTextAreaAction saveXmlTextAreaAction = new SaveXmlTextAreaAction(resultArea, "Save Response");
456 		popup.add( saveXmlTextAreaAction);
457       
458       resultArea.setRightClickPopup( popup );
459       resultArea.getInputHandler().addKeyBinding( "A+ENTER", submitButton.getAction() );
460       resultArea.getInputHandler().addKeyBinding( "A+X", cancelButton.getAction() );
461       resultArea.getInputHandler().addKeyBinding( "A+V", validateResponseXmlAction );
462       resultArea.getInputHandler().addKeyBinding( "A+F", formatXmlAction );
463       resultArea.getInputHandler().addKeyBinding( "A+S", saveXmlTextAreaAction );
464       resultArea.getInputHandler().addKeyBinding( "S+TAB", moveFocusAction );
465       
466       resultAreaSplit.setTopComponent( resultArea );
467 		resultAreaSplit.setBottomComponent( scrollPane);
468       resultAreaSplit.setDividerLocation( 1.0 );
469       
470       return resultAreaSplit;
471    }
472 
473    private Component buildInputUI()
474    {
475       inputArea = new JXmlTextArea();
476       inputArea.setMinimumSize( new Dimension( 50, 50 ));
477       inputArea.setToolTipText( "Request Area" );
478       inputArea.setText( request.getRequestContent() );
479       inputArea.setCaretPosition( 0 );
480       inputArea.setDiscardEditsOnSet( false );
481       inputArea.addFocusListener( new InputAreaFocusListener());
482       
483       DefaultListModel listModel = new DefaultListModel();
484       JList list = new JList( listModel );
485       list.setToolTipText( "Request Validation Errors" );
486       list.addMouseListener( new ValidationListMouseAdapter( list, inputArea ));
487 		JScrollPane scrollPane = new JScrollPane( list );
488 		scrollPane.setVisible( false );
489 		
490 		JSplitPane inputAreaSplit = UISupport.createVerticalSplit();
491       
492       JPopupMenu inputPopup = new JPopupMenu();
493       ValidateRequestXmlAction validateRequestXmlAction = new ValidateRequestXmlAction( request, scrollPane, listModel, inputAreaSplit, inputArea );
494 		inputPopup.add( validateRequestXmlAction);
495       FormatXmlAction formatXmlAction = new FormatXmlAction(inputArea);
496 		inputPopup.add( formatXmlAction);
497       inputPopup.addSeparator();
498       inputPopup.add( inputArea.getUndoAction() );
499       inputPopup.add( inputArea.getRedoAction() );
500       inputPopup.add( inputArea.getCopyAction() );
501       inputPopup.add( inputArea.getCutAction() );
502       inputPopup.add( inputArea.getPasteAction() );
503       inputPopup.addSeparator();
504       inputPopup.add( inputArea.getFindAndReplaceAction() );
505       inputPopup.addSeparator();
506       SaveXmlTextAreaAction saveXmlTextAreaAction = new SaveXmlTextAreaAction(inputArea, "Save Request");
507 		inputPopup.add( saveXmlTextAreaAction);
508 		
509       inputArea.setRightClickPopup( inputPopup );
510       
511       inputArea.getDocument().addDocumentListener( new DocumentListener() {
512 
513          public void insertUpdate(DocumentEvent e)
514          {
515             request.setRequest( inputArea.getText() );
516          }
517 
518          public void removeUpdate(DocumentEvent e)
519          {
520             request.setRequest( inputArea.getText() );
521          }
522 
523          public void changedUpdate(DocumentEvent e)
524          {
525             
526          }} );
527       
528       inputArea.getInputHandler().addKeyBinding( "A+ENTER", submitButton.getAction() );
529       inputArea.getInputHandler().addKeyBinding( "A+X", cancelButton.getAction() );
530       inputArea.getInputHandler().addKeyBinding( "A+V", validateRequestXmlAction );
531       inputArea.getInputHandler().addKeyBinding( "A+F", formatXmlAction );
532       inputArea.getInputHandler().addKeyBinding( "A+S", saveXmlTextAreaAction );
533       inputArea.getInputHandler().addKeyBinding( "S+TAB", moveFocusAction );
534      
535       inputAreaSplit.setTopComponent( inputArea );
536 		inputAreaSplit.setBottomComponent( scrollPane);
537       inputAreaSplit.setDividerLocation( 1.0 );
538       
539       return inputAreaSplit;
540    }
541 
542    private JComponent buildSearchBar()
543    {
544       endpointCombo = new JComboBox( endpointsModel);
545       endpointCombo.setToolTipText( endpointsModel.getSelectedItem().toString() );
546       endpointCombo.setPreferredSize( new Dimension( 300, 20 ));
547       
548       endpointsModel.setSelectedItem( request.getEndpoint());
549       
550       endpointCombo.addItemListener( new ItemListener() {
551 
552          public void itemStateChanged(ItemEvent e)
553          {
554          	Object item = endpointCombo.getSelectedItem();
555             if( item == null )
556             {
557             	endpointCombo.setToolTipText( "- no endpoint set for request -" );
558             }
559             else
560             {
561 					String selectedItem = item.toString();
562 	            endpointCombo.setToolTipText( selectedItem );
563             }
564          
565             submitButton.setEnabled( submit == null && request.getEndpoint() != null && request.getEndpoint().trim().length() > 0 );
566          }});
567       
568       encodingCombo = new JComboBox();
569       encodingCombo.setEditable( true );
570       encodingCombo.addItem( "UTF-8" );
571       encodingCombo.addItem( "iso-8859-1" );
572       encodingCombo.setSelectedItem( request.getEncoding() );
573       encodingCombo.setToolTipText( "Sets the encoding to use for the request" );
574       
575       encodingCombo.addItemListener( new ItemListener() {
576 
577          public void itemStateChanged(ItemEvent e)
578          {
579             request.setEncoding( encodingCombo.getSelectedItem().toString() );
580          }});
581       
582       ButtonBarBuilder builder = new ButtonBarBuilder();
583       builder.addFixed( submitButton );
584       builder.addRelatedGap();
585       builder.addFixed( addAssertionButton );
586       builder.addRelatedGap();
587       builder.addFixed( recreateButton );
588       builder.addRelatedGap();
589       builder.addFixed( createEmptyButton );
590       builder.addRelatedGap();
591       builder.addFixed( cloneButton );
592       builder.addRelatedGap();
593       builder.addFixed( cancelButton );
594       builder.addUnrelatedGap();
595       builder.addFixed( endpointCombo );
596       builder.addRelatedGap();
597       builder.addFixed( encodingCombo );
598       builder.addRelatedGap();
599       builder.addFixed( splitButton );
600 
601 
602       builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
603       return builder.getPanel();
604    }
605 
606    public void setEnabled( boolean enabled )
607    {
608       endpointCombo.setEnabled( enabled );
609       inputArea.setEditable( enabled );
610       resultArea.setEditable( enabled );
611       addAssertionButton.setEnabled( enabled );
612       submitButton.setEnabled( enabled && request.getEndpoint() != null && request.getEndpoint().trim().length() > 0);
613       recreateButton.setEnabled( enabled );
614       createEmptyButton.setEnabled( enabled );
615       cloneButton.setEnabled( enabled );
616       encodingCombo.setEnabled( enabled );
617    }
618    
619    public class ValidateAction extends AbstractAction
620    {
621       public ValidateAction()
622       {
623          putValue( Action.SMALL_ICON, SoapUI.createImageIcon( "/validate_request.gif"));
624          putValue( Action.SHORT_DESCRIPTION, "Validates the current response with the current assertions" );
625       }
626 
627       public void actionPerformed( ActionEvent e )
628       {
629          request.setResponse( resultArea.getText() );
630       }
631    }
632    
633    public class SubmitAction extends AbstractAction
634    {
635       public SubmitAction()
636       {
637          putValue( Action.SMALL_ICON, SoapUI.createImageIcon( "/submit_request.gif"));
638          putValue( Action.SHORT_DESCRIPTION, "Submit request to specified endpoint URL" );
639          putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, KeyEvent.ALT_MASK ));
640       }
641 
642       public void actionPerformed( ActionEvent e )
643       {
644       	if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
645       	{
646       		if( UISupport.confirm( "Cancel current request?", "Submit Request" ))
647       		{
648       			submit.cancel();
649       		}
650       		else return;
651       	}
652       	
653       	submit = request.submit();
654       }
655    }
656 
657    private class CancelAction extends AbstractAction
658    {
659       public CancelAction()
660       {
661          super();
662          putValue( Action.SMALL_ICON, SoapUI.createImageIcon( "/cancel_request.gif"));
663          putValue( Action.SHORT_DESCRIPTION, "Aborts ongoing request" );
664          putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_X, KeyEvent.ALT_MASK ));
665       }
666 
667       public void actionPerformed( ActionEvent e )
668       {
669       	if( submit == null ) return;
670       	
671          cancelButton.setEnabled( false );
672          WsdlTestRequestDesktopPanel.this.setEnabled( true );
673          submit.cancel();
674       }
675    }
676 
677    private class InternalSubmitListener implements SubmitListener
678    {
679       private long startTime;
680       private SimpleDateFormat sdf;
681 
682       private InternalSubmitListener()
683       {
684          sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
685       }
686 
687       public boolean beforeSubmit(Submit submit)
688       {
689       	if( submit.getRequest() != request ) return true;
690       	
691          setEnabled( false );
692          cancelButton.setEnabled( WsdlTestRequestDesktopPanel.this.submit != null );
693          startTime = System.currentTimeMillis();
694          return true;
695       }
696 
697       public void afterSubmit(Submit submit)
698       {
699       	if( submit.getRequest() != request ) return;
700       	Status status = submit.getStatus();
701       	
702          if( status != Status.CANCELED )
703          {
704             cancelButton.setEnabled( false );
705             setEnabled( true );
706             
707             request.setResponse( submit.getResponse( false ).getContentAsString() );
708          }
709          
710          String message = null;
711          String infoMessage = null;
712          String requestName = request.getOperation().getInterface().getName() + "." + 
713             request.getOperation().getName() + ":" + request.getName();
714 
715          if( status == Status.CANCELED ) 
716          {
717             message = "CANCELED";
718             infoMessage = "[" + requestName + "] - CANCELED";
719          }
720          else
721          {
722             if( status == Status.ERROR )
723             {
724                message = "Error getting response; " + submit.getError().getMessage();
725                infoMessage = "Error getting response for [" + requestName + "]; " + submit.getError().getMessage();
726             }
727             else
728             {
729                message = "request time: " + submit.getTimeTaken() + "ms (" + 
730                   submit.getResponse( false ).getContentLength() + " bytes)";   
731                infoMessage = "Got response for [" + requestName + "] in " + submit.getTimeTaken() + "ms (" + 
732                   submit.getResponse( false ).getContentLength() + " bytes)";   
733                
734                resultArea.requestFocus();
735             }
736          }
737          
738          log.info( infoMessage );
739          
740          String logText = logArea.getText() + sdf.format( new Date( startTime )) + " - " + message + "\r\n";
741          logArea.setText( logText );
742          logArea.setCaretPosition( logText.length() );
743          statusLabel.setText( message  );
744          
745          WsdlTestRequestDesktopPanel.this.submit = null;
746       }
747    }
748    
749    private class InternalPropertyChangeListener implements PropertyChangeListener
750    {
751       public void propertyChange(PropertyChangeEvent evt)
752       {
753          String propertyName = evt.getPropertyName();
754          if( propertyName.equals( WsdlRequest.RESPONSE_PROPERTY ))
755          {
756             resultArea.setText( request.getResponseContent() );
757             resultArea.setCaretPosition( 0 );
758          }
759          else if( propertyName.equals( WsdlRequest.ENCODING_PROPERTY ))
760          {
761             encodingCombo.setSelectedItem( request.getEncoding() );
762          }
763          else if( propertyName.equals( WsdlTestRequest.STATUS_PROPERTY ))
764          {
765             assertionListModel.refresh(); 
766          }
767          else if( propertyName.equals( WsdlRequest.REQUEST_PROPERTY ))
768          {
769          	String requestContent = request.getRequestContent();
770             if( !requestContent.equals( inputArea.getText()))
771             	inputArea.setText( requestContent );
772          }
773       }
774    }
775    
776    private class MoveFocusAction extends AbstractAction
777    {
778 		public void actionPerformed(ActionEvent e)
779 		{
780 			if( inputArea.hasFocus() )
781 				resultArea.requestFocus();
782 			else 
783 			   inputArea.requestFocus();
784 		}
785    }
786    
787    private final class InputAreaFocusListener implements FocusListener
788 	{
789 		public void focusGained(FocusEvent e)
790 		{
791 			// dont resize if split has been dragged 
792 			if( ((SoapUISplitPaneUI)requestSplitPane.getUI()).hasBeenDragged() ) return;
793 			
794 			int pos = requestSplitPane.getDividerLocation();
795 			if( pos >= 600 ) return;
796 			if( requestSplitPane.getMaximumDividerLocation() > 700 )
797 				requestSplitPane.setDividerLocation( 600 );
798 			else
799 			   requestSplitPane.setDividerLocation( 0.8 );
800 		}
801 
802 		public void focusLost(FocusEvent e)
803 		{
804 		}
805 	}
806    
807    private final class ResultAreaFocusListener implements FocusListener
808 	{
809 		public void focusGained(FocusEvent e)
810 		{
811 			if( ((SoapUISplitPaneUI)requestSplitPane.getUI()).hasBeenDragged() || resultArea.getText().trim().length() == 0 ) 
812 				return;
813 			
814 			int pos = requestSplitPane.getDividerLocation();
815 			int maximumDividerLocation = requestSplitPane.getMaximumDividerLocation();
816 			if( pos + 600 < maximumDividerLocation ) return;
817 			
818 			if( maximumDividerLocation > 700 )
819 				requestSplitPane.setDividerLocation( maximumDividerLocation-600 );
820 			else
821 				requestSplitPane.setDividerLocation( 0.2 );
822 		}
823 
824 		public void focusLost(FocusEvent e)
825 		{
826 		}
827 	}
828 
829    public ModelItem getModelItem()
830 	{
831 		return requestStep;
832 	}
833 
834 	public boolean onClose()
835 	{
836 		if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
837 		{
838 			int retVal = JOptionPane.showConfirmDialog( SoapUI.getInstance().getFrame(), "Cancel request before closing?",
839 					 "Closing window", JOptionPane.YES_NO_CANCEL_OPTION);
840 			if( retVal == JOptionPane.CANCEL_OPTION ) return false;
841 			
842 			if( retVal == JOptionPane.YES_OPTION && submit.getStatus() == Submit.Status.RUNNING )
843 				submit.cancel();
844 		}
845 		
846       request.removeSubmitListener( internalSubmitListener );
847       request.removePropertyChangeListener( internalPropertyChangeListener );
848       request.getOperation().getInterface().removePropertyChangeListener( internalPropertyChangeListener );
849       assertionListModel.release();
850       endpointsModel.release();
851       
852       return true;
853 	}
854 
855 	public JComponent getComponent()
856 	{
857 		return this;
858 	}
859 	
860    private final class ValidationListMouseAdapter extends MouseAdapter
861 	{
862 		private final JList list;
863 		private final JXmlTextArea textArea;
864 
865 		public ValidationListMouseAdapter(JList list, JXmlTextArea textArea)
866 		{
867 			this.list = list;
868 			this.textArea = textArea;
869 		}
870 
871 		public void mouseClicked(MouseEvent e)
872 		{
873 		   if( e.getClickCount() < 2 ) return;
874 		
875 		   int ix = list.getSelectedIndex();
876 		   if( ix == -1 ) return;
877 		   
878 		   Object obj = list.getModel().getElementAt( ix );
879 		   if( obj instanceof AssertionError )
880 		   {
881 		   	AssertionError error = (AssertionError) obj;
882 		   	if( error.getLineNumber() >= 0 )
883 		   	{
884 		   		textArea.setCaretPosition( textArea.getLineStartOffset( error.getLineNumber()-1 ) );
885 		   		textArea.requestFocus();
886 		   	}
887 		   	else Toolkit.getDefaultToolkit().beep();
888 		   }
889 		   else Toolkit.getDefaultToolkit().beep();
890 		}
891 	}
892 }