View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 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.request;
    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.FocusAdapter;
    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.beans.PropertyChangeEvent;
    25  import java.beans.PropertyChangeListener;
    26  import java.security.cert.Certificate;
    27
    28  import javax.swing.AbstractAction;
    29  import javax.swing.Action;
    30  import javax.swing.BorderFactory;
    31  import javax.swing.Box;
    32  import javax.swing.JButton;
    33  import javax.swing.JComboBox;
    34  import javax.swing.JComponent;
    35  import javax.swing.JEditorPane;
    36  import javax.swing.JPanel;
    37  import javax.swing.JPopupMenu;
    38  import javax.swing.JScrollPane;
    39  import javax.swing.JSeparator;
    40  import javax.swing.JSplitPane;
    41  import javax.swing.JTabbedPane;
    42  import javax.swing.JTable;
    43  import javax.swing.JToggleButton;
    44  import javax.swing.JToolBar;
    45  import javax.swing.SwingUtilities;
    46  import javax.swing.event.ChangeEvent;
    47  import javax.swing.event.ChangeListener;
    48  import javax.swing.event.TableModelEvent;
    49  import javax.swing.event.TableModelListener;
    50  import javax.swing.text.html.HTMLEditorKit;
    51
    52  import org.apache.log4j.Logger;
    53
    54  import com.eviware.soapui.SoapUI;
    55  import com.eviware.soapui.impl.wsdl.WsdlRequest;
    56  import com.eviware.soapui.impl.wsdl.WsdlSubmitContext;
    57  import com.eviware.soapui.impl.wsdl.actions.request.AddRequestToMockServiceAction;
    58  import com.eviware.soapui.impl.wsdl.actions.request.CloneRequestAction;
    59  import com.eviware.soapui.impl.wsdl.actions.request.CreateEmptyRequestAction;
    60  import com.eviware.soapui.impl.wsdl.actions.request.RecreateRequestAction;
    61  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
    62  import com.eviware.soapui.impl.wsdl.panels.attachments.AttachmentPanel;
    63  import com.eviware.soapui.impl.wsdl.panels.request.actions.WSIValidateRequestAction;
    64  import com.eviware.soapui.impl.wsdl.panels.request.components.RequestMessageXmlEditor;
    65  import com.eviware.soapui.impl.wsdl.panels.request.components.RequestXmlDocument;
    66  import com.eviware.soapui.impl.wsdl.panels.request.components.ResponseMessageXmlEditor;
    67  import com.eviware.soapui.impl.wsdl.panels.request.components.ResponseXmlDocument;
    68  import com.eviware.soapui.impl.wsdl.panels.request.components.SoapMessageXmlEditor;
    69  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlDocument;
    70  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.views.source.XmlSourceEditorView;
    71  import com.eviware.soapui.impl.wsdl.panels.support.EndpointsComboBoxModel;
    72  import com.eviware.soapui.impl.wsdl.submit.transports.http.SSLInfo;
    73  import com.eviware.soapui.impl.wsdl.submit.transports.http.WsdlResponse;
    74  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
    75  import com.eviware.soapui.model.ModelItem;
    76  import com.eviware.soapui.model.iface.Submit;
    77  import com.eviware.soapui.model.iface.SubmitContext;
    78  import com.eviware.soapui.model.iface.SubmitListener;
    79  import com.eviware.soapui.model.iface.Request.SubmitException;
    80  import com.eviware.soapui.model.iface.Submit.Status;
    81  import com.eviware.soapui.settings.UISettings;
    82  import com.eviware.soapui.support.UISupport;
    83  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
    84  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
    85  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
    86  import com.eviware.soapui.support.components.JXToolBar;
    87  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
    88  import com.eviware.soapui.support.types.StringToStringMap;
    89  import com.eviware.soapui.support.xml.JXEditTextArea;
    90  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
    91
    92  /***
    93   * Abstract DesktopPanel for WsdlRequests
    94   *
    95   * @author Ole.Matzura
    96   */
    97
    98  public class AbstractWsdlRequestDesktopPanel<T extends ModelItem, T2 extends WsdlRequest> extends ModelItemDesktopPanel<T>
    99  {
    100 	private final static Logger log = Logger.getLogger(AbstractWsdlRequestDesktopPanel.class);
    101
    102 	private JComboBox endpointCombo;
    103 	private JButton submitButton;
    104 	private JButton cancelButton;
    105 	private EndpointsComboBoxModel endpointsModel;
    106 	private JEditorStatusBarWithProgress statusBar;
    107 	private JButton splitButton;
    108 	private Submit submit;
    109 	private JButton recreateButton;
    110 	private JButton cloneButton;
    111 	private JButton createEmptyButton;
    112 	private InternalSubmitListener internalSubmitListener;
    113 	private JSplitPane requestSplitPane;
    114 	private MoveFocusAction moveFocusAction;
    115 	private ClosePanelAction closePanelAction = new ClosePanelAction();
    116 	private T2 request;
    117
    118 	private SoapMessageXmlEditor requestEditor;
    119 	private SoapMessageXmlEditor responseEditor;
    120
    121 	//public WSIValidateRequestAction wsiValidateAction;
    122
    123 	private JTabbedPane requestTabs;
    124 	private JPanel requestTabPanel;
    125 	private JToggleButton tabsButton;
    126
    127 	public boolean responseHasFocus;
    128
    129 	private JTabbedPane requestEditorTabs;
    130 	private JTabbedPane responseEditorTabs;
    131
    132 	private JPanel requestEditorTabPanel;
    133 	private JPanel responseEditorTabPanel;
    134 	private AttachmentPropertyChangeListener attachmentsPropertyChangeListener = new AttachmentPropertyChangeListener();
    135 	private StringToStringMapTableModel requestHeadersModel;
    136 	private JTable requestHeadersTable;
    137 	private StringToStringMapTableModel responseHeadersModel;
    138
    139 	private JEditorPane sslInfoPane;
    140 	private JButton addToMockServiceButton;
    141 	//private JButton addAsMockResponseStepButton;
    142
    143 //	private DefaultActionList formEditorActions;
    144
    145 	private AbstractAction wsiValidateAction;
    146
    147 	private AttachmentPanel requestAttachmentPanel;
    148 	private AttachmentPanel responseAttachmentPanel;
    149
    150 	public AbstractWsdlRequestDesktopPanel(T modelItem)
    151 	{
    152 		super(modelItem);
    153 	}
    154
    155 	protected void init(T2 request)
    156 	{
    157 		this.request = request;
    158
    159 		this.endpointsModel = new EndpointsComboBoxModel(request);
    160 		internalSubmitListener = createSubmitListener();
    161
    162 		request.addSubmitListener(internalSubmitListener);
    163
    164 		add(buildContent(), BorderLayout.CENTER);
    165 		add(buildToolbar(), BorderLayout.NORTH);
    166 		add(buildStatusLabel(), BorderLayout.SOUTH);
    167
    168 		setPreferredSize(new Dimension(600, 500));
    169
    170 		request.addPropertyChangeListener( attachmentsPropertyChangeListener );
    171
    172 		addFocusListener( new FocusAdapter() {
    173
    174 			@Override
    175 			public void focusGained( FocusEvent e )
    176 			{
    177 				if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
    178 					responseEditor.requestFocusInWindow();
    179 				else
    180 					requestEditor.requestFocusInWindow();
    181 			}} );
    182 	}
    183
    184 	protected InternalSubmitListener createSubmitListener()
    185 	{
    186 		return new InternalSubmitListener();
    187 	}
    188
    189 	public final T2 getRequest()
    190 	{
    191 		return request;
    192 	}
    193
    194 	public final SoapMessageXmlEditor getRequestEditor()
    195 	{
    196 		return requestEditor;
    197 	}
    198
    199 	public final SoapMessageXmlEditor getResponseEditor()
    200 	{
    201 		return responseEditor;
    202 	}
    203
    204 	public Submit getSubmit()
    205 	{
    206 		return submit;
    207 	}
    208
    209 	protected JComponent buildStatusLabel()
    210 	{
    211 		statusBar = new JEditorStatusBarWithProgress();
    212 		statusBar.setBorder( BorderFactory.createEmptyBorder( 1, 0, 0, 0 ));
    213
    214 		return statusBar;
    215 	}
    216
    217 	public JEditorStatusBarWithProgress getStatusBar()
    218 	{
    219 		return statusBar;
    220 	}
    221
    222 	@SuppressWarnings("unchecked")
    223 	protected JComponent buildContent()
    224 	{
    225 		requestSplitPane = UISupport.createHorizontalSplit();
    226 		requestSplitPane.setResizeWeight(0.5);
    227 		requestSplitPane.setBorder(null);
    228
    229 		submitButton = createActionButton(new SubmitAction(), true);
    230 		cancelButton = createActionButton(new CancelAction(), false);
    231 		splitButton = createActionButton(new ChangeSplitPaneOrientationAction(requestSplitPane), true);
    232
    233 		tabsButton = new JToggleButton( new ChangeToTabsAction() );
    234 		tabsButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
    235
    236 		recreateButton = createActionButton(new RecreateRequestAction(request), true);
    237 		addToMockServiceButton = createActionButton(
    238 					SwingActionDelegate.createDelegate( AddRequestToMockServiceAction.SOAPUI_ACTION_ID, request, null, "/addToMockService.gif" ), true );
    239
    240 		cloneButton = createActionButton(
    241 					SwingActionDelegate.createDelegate( CloneRequestAction.SOAPUI_ACTION_ID, request, null, "/clone_request.gif" ), true );
    242
    243 		createEmptyButton = createActionButton(new CreateEmptyRequestAction(request), true);
    244
    245 		submitButton.setEnabled(request.getEndpoint() != null && request.getEndpoint().trim().length() > 0);
    246 		wsiValidateAction =
    247 			SwingActionDelegate.createDelegate( new WSIValidateRequestAction(), request, "alt W" );
    248 		wsiValidateAction.setEnabled( request.getResponse() != null );
    249
    250 		moveFocusAction = new MoveFocusAction();
    251
    252 		requestEditor = buildRequestEditor();
    253 		responseEditor = buildResponseEditor();
    254
    255 		requestEditorTabs = new JTabbedPane( JTabbedPane.BOTTOM );
    256 		requestEditorTabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
    257 		requestEditorTabs.addTab( "SOAP Request", requestEditor );
    258 		requestAttachmentPanel = new AttachmentPanel( request, true );
    259 		requestEditorTabs.addTab( "Request Attachments (" + request.getAttachmentCount() + ")"
    260 				, requestAttachmentPanel);
    261 		requestEditorTabs.addTab( "HTTP Headers (" + request.getRequestHeaders().size() + ")", createRequestHttpHeadersPanel() );
    262 		requestEditorTabs.addChangeListener( new ChangeListener() {
    263
    264 			public void stateChanged( ChangeEvent e )
    265 			{
    266 				SwingUtilities.invokeLater( new Runnable() {
    267
    268 					public void run()
    269 					{
    270 						int ix = requestEditorTabs.getSelectedIndex();
    271 						if( ix == 0 )
    272 						  requestEditor.requestFocus();
    273 					}}  );
    274
    275 			}} );
    276
    277 		responseEditorTabs = new JTabbedPane( JTabbedPane.BOTTOM );
    278 		responseEditorTabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
    279 		responseEditorTabs.addTab( "SOAP Response", responseEditor );
    280 		responseAttachmentPanel = new AttachmentPanel( request, false );
    281 		responseEditorTabs.addTab( "Response Attachments (" + (request.getResponse() == null ? 0 :
    282 			request.getResponse().getAttachments().length) + ")", responseAttachmentPanel);
    283 		responseEditorTabs.addTab( "HTTP Headers", createResponseHttpHeadersPanel() );
    284 		String sslInfoTabTitle = "SSL Info";
    285 		if( request.getResponse() != null && ((WsdlResponse)request.getResponse()).getSSLInfo() != null )
    286 			sslInfoTabTitle += " (" + ((WsdlResponse)request.getResponse()).getSSLInfo().getPeerCertificates().length + " certs)";
    287 		else
    288 			sslInfoTabTitle += " (-)";
    289
    290 		responseEditorTabs.addTab( sslInfoTabTitle, createSSLInfoPanel() );
    291 		responseEditorTabs.addChangeListener( new ChangeListener() {
    292
    293 			public void stateChanged( ChangeEvent e )
    294 			{
    295 				SwingUtilities.invokeLater( new Runnable() {
    296
    297 					public void run()
    298 					{
    299 						int ix = responseEditorTabs.getSelectedIndex();
    300 						if( ix == 0 )
    301 							responseEditor.requestFocus();
    302 					}}  );
    303
    304 			}} );
    305
    306 		requestTabs = new JTabbedPane();
    307 		requestTabs.addChangeListener( new ChangeListener() {
    308
    309 			public void stateChanged( ChangeEvent e )
    310 			{
    311 				SwingUtilities.invokeLater( new Runnable() {
    312
    313 					public void run()
    314 					{
    315 						int ix = requestTabs.getSelectedIndex();
    316 						if( ix == 0 && requestEditorTabs.getSelectedIndex() == 0 )
    317 							requestEditor.requestFocus();
    318 						else if( ix == 1 && responseEditorTabs.getSelectedIndex() == 0 )
    319 							responseEditor.requestFocus();
    320 					}} );
    321 			}} );
    322
    323 	   requestTabPanel = UISupport.createTabPanel( requestTabs, true );
    324
    325 	   requestEditorTabPanel = UISupport.createTabPanel(requestEditorTabs, false);
    326 		responseEditorTabPanel = UISupport.createTabPanel(responseEditorTabs, false);
    327
    328 		if( request.getSettings().getBoolean( UISettings.START_WITH_REQUEST_TABS ))
    329 	   {
    330 	   	requestTabs.addTab( "Request", requestEditorTabPanel );
    331 	   	requestTabs.addTab( "Response", responseEditorTabPanel );
    332 	   	splitButton.setEnabled( false );
    333 	   	tabsButton.setSelected( true );
    334
    335 	   	return requestTabPanel;
    336 	   }
    337 	   else
    338 	   {
    339 	   	requestSplitPane.setTopComponent(requestEditorTabPanel);
    340 	   	requestSplitPane.setBottomComponent(responseEditorTabPanel);
    341 	   	requestSplitPane.setDividerLocation(0.5);
    342 	   	return requestSplitPane;
    343 	   }
    344 	}
    345
    346 	private Component createSSLInfoPanel()
    347 	{
    348 		JPanel panel = new JPanel( new BorderLayout());
    349
    350 		sslInfoPane = new JEditorPane();
    351 		sslInfoPane.setEditorKit( new HTMLEditorKit() );
    352 		panel.add( new JScrollPane( sslInfoPane ));
    353
    354 		return panel;
    355 	}
    356
    357 	private void updateSSLInfo( SSLInfo sslInfo )
    358 	{
    359 		String sslInfoTabTitle = "SSL Info";
    360
    361 		if( sslInfo == null )
    362 		{
    363 			sslInfoPane.setText( "<html><body>Not an SSL connection</body></html>" );
    364 			sslInfoTabTitle += " (-)";
    365 		}
    366 		else
    367 		{
    368 			StringBuffer buf = new StringBuffer( "<html><body><table cellpadding=1 cellspacing=1 border=0>" );
    369
    370 			buf.append( "<tr><td><b>CipherSuite:</b></td><td align=left valign=top>" ).
    371 				append( sslInfo.getCipherSuite().toString() ).append( "</td></tr>");
    372
    373 			if( sslInfo.getLocalPrincipal() != null )
    374 				buf.append( "<tr><td><b>LocalPrincipal:</b></td><td align=left valign=top>" ).
    375 					append( sslInfo.getLocalPrincipal().getName() ).append( "</td></tr>");
    376
    377 			Certificate[] localCertificates = sslInfo.getLocalCertificates();
    378
    379 			if( localCertificates != null)
    380 			{
    381 				buf.append( "</table><table cellpadding=0 cellspacing=0 border=0>" );
    382
    383 				int cnt = 1;
    384 				for( Certificate cert : localCertificates )
    385 				{
    386 					buf.append( "<tr><td><b>Local Certificate " ).append( cnt++ ).
    387 						append( ":</b><pre><font size=-1>" ).
    388 						append( cert.toString() ).append( "</font></pre></td></tr>");
    389
    390 				}
    391
    392 				buf.append( "</table><table cellpadding=1 cellspacing=1 border=0>" );
    393 			}
    394
    395 			if( sslInfo.getPeerPrincipal() != null )
    396 				buf.append( "<tr><td><b>PeerPrincipal:</b></td><td align=left valign=top>" ).
    397 					append( sslInfo.getPeerPrincipal().toString() ).append( "</td></tr>");
    398
    399 			Certificate[] peerCertificates = sslInfo.getPeerCertificates();
    400 			if( peerCertificates != null)
    401 			{
    402 				buf.append( "</table><table cellpadding=0 cellspacing=0 border=0>" );
    403
    404 				int cnt = 1;
    405 				for( Certificate cert : peerCertificates )
    406 				{
    407 					buf.append( "<tr><td colspan=2><b>Peer Certificate " ).append( cnt++ ).
    408 						append( ":</b><pre><font size=-1>" ).
    409 						append( cert.toString() ).append( "</font></pre></td></tr>");
    410 				}
    411
    412 				buf.append( "</table><table cellpadding=0 cellspacing=0 border=0>" );
    413 			}
    414
    415 			buf.append(  "</table></body></html>" );
    416 			sslInfoPane.setText( buf.toString() );
    417
    418 			sslInfoTabTitle += " (" + sslInfo.getPeerCertificates().length + " certs)";
    419 		}
    420
    421 		responseEditorTabs.setTitleAt( 3, sslInfoTabTitle );
    422 	}
    423
    424 	private Component createResponseHttpHeadersPanel()
    425 	{
    426 		responseHeadersModel = new StringToStringMapTableModel(
    427 							request.getResponse() == null ? new StringToStringMap() :
    428 								request.getResponse().getResponseHeaders(), "Header", "Value", false );
    429
    430 		responseHeadersModel.addTableModelListener( new TableModelListener()
    431 		{
    432 			public void tableChanged( TableModelEvent arg0 )
    433 			{
    434 				responseEditorTabs.setTitleAt( 2, "HTTP Headers (" + responseHeadersModel.getRowCount() + ")");
    435 			}} );
    436
    437 		JTable responseHeadersTable = new JTable( responseHeadersModel );
    438 		return new JScrollPane( responseHeadersTable );
    439 	}
    440
    441 	private Component createRequestHttpHeadersPanel()
    442 	{
    443 		requestHeadersModel = new StringToStringMapTableModel( request.getRequestHeaders(), "Header", "Value", true );
    444 		requestHeadersModel.addTableModelListener( new TableModelListener()
    445 		{
    446 			public void tableChanged( TableModelEvent arg0 )
    447 			{
    448 				getRequest().setRequestHeaders( requestHeadersModel.getData() );
    449 				requestEditorTabs.setTitleAt( 2, "HTTP Headers (" + requestHeadersModel.getRowCount() + ")");
    450 			}} );
    451
    452 		requestHeadersTable = new JTable( requestHeadersModel );
    453 		JPanel panel = new JPanel( new BorderLayout() );
    454
    455 		panel.add( new JScrollPane( requestHeadersTable ), BorderLayout.CENTER );
    456
    457 		JXToolBar builder = UISupport.createToolbar();
    458 		builder.addFixed( new JButton( new AbstractAction( "Add" ) {
    459
    460 			public void actionPerformed( ActionEvent arg0 )
    461 			{
    462 				Object header = UISupport.prompt( "Specify name of header to add", "Add HTTP Header", "" );
    463 				if( header != null )
    464 				{
    465 					requestHeadersModel.add( header.toString(), "" );
    466 				}
    467 			}} ));
    468 		builder.addRelatedGap();
    469 		builder.addFixed( new JButton( new AbstractAction("Remove" ){
    470
    471 			public void actionPerformed( ActionEvent arg0 )
    472 			{
    473 				int row = requestHeadersTable.getSelectedRow();
    474 				if( row != -1 && UISupport.confirm( "Delete selected header?", "Remove Header" ) )
    475 				{
    476 					requestHeadersModel.remove( row );
    477 				}
    478 			}} ));
    479
    480
    481 //		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
    482 		builder.addGlue();
    483 		builder.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction(HelpUrls.HEADERS_HELP_URL)));
    484
    485 		panel.add( builder, BorderLayout.SOUTH );
    486
    487 		return panel;
    488 	}
    489
    490 	protected SoapMessageXmlEditor buildResponseEditor()
    491 	{
    492 		return new WsdlResponseMessageEditor( new ResponseXmlDocument( request ));
    493 	}
    494
    495 	protected SoapMessageXmlEditor buildRequestEditor()
    496 	{
    497 		return new WsdlRequestMessageEditor( new RequestXmlDocument( request ));
    498 	}
    499
    500 	protected JComponent buildToolbar()
    501 	{
    502 		endpointCombo = new JComboBox(endpointsModel);
    503 		endpointCombo.setToolTipText(endpointsModel.getSelectedItem().toString());
    504
    505 		endpointCombo.addItemListener(new ItemListener()
    506 		{
    507 			public void itemStateChanged(ItemEvent e)
    508 			{
    509 				Object item = endpointCombo.getSelectedItem();
    510 				if (item == null)
    511 				{
    512 					endpointCombo.setToolTipText("- no endpoint set for request -");
    513 				}
    514 				else
    515 				{
    516 					String selectedItem = item.toString();
    517 					endpointCombo.setToolTipText(selectedItem);
    518 				}
    519
    520 				submitButton.setEnabled(submit == null && request.getEndpoint() != null
    521 						&& request.getEndpoint().trim().length() > 0);
    522 			}
    523 		});
    524
    525 		JXToolBar toolbar =  UISupport.createToolbar();
    526
    527 		toolbar.add( submitButton );
    528 		insertButtons( toolbar );
    529
    530 		toolbar.add( addToMockServiceButton);
    531 //		toolbar.add( addAsMockResponseStepButton);
    532
    533 		toolbar.add(recreateButton);
    534 		toolbar.add(createEmptyButton);
    535 		toolbar.add(cloneButton);
    536 		toolbar.add(cancelButton);
    537 		toolbar.addSeparator();
    538 		toolbar.add(endpointCombo);
    539
    540 		toolbar.add( Box.createHorizontalGlue() );
    541 		toolbar.add( tabsButton );
    542 		toolbar.add(splitButton);
    543 		toolbar.add(UISupport.createToolbarButton(new ShowOnlineHelpAction(getHelpUrl())));
    544
    545 		return toolbar;
    546 	}
    547
    548 	protected String getHelpUrl()
    549 	{
    550 		return HelpUrls.REQUESTEDITOR_HELP_URL;
    551 	}
    552
    553 	protected void insertButtons(JToolBar toolbar)
    554 	{
    555 	}
    556
    557 	public void setEnabled(boolean enabled)
    558 	{
    559 		endpointCombo.setEnabled(enabled);
    560 		requestEditor.setEditable(enabled);
    561 		responseEditor.setEditable(enabled);
    562
    563 		submitButton.setEnabled(enabled && request.getEndpoint() != null
    564 				&& request.getEndpoint().trim().length() > 0);
    565 		recreateButton.setEnabled(enabled);
    566 		createEmptyButton.setEnabled(enabled);
    567 		cloneButton.setEnabled(enabled);
    568
    569 		statusBar.setIndeterminate( !enabled );
    570 	}
    571
    572 	private final class AttachmentPropertyChangeListener implements PropertyChangeListener
    573 	{
    574 		public void propertyChange(PropertyChangeEvent evt)
    575 		{
    576 			if( evt.getPropertyName().equals( WsdlRequest.ATTACHMENTS_PROPERTY ))
    577 			{
    578 				requestEditorTabs.setTitleAt( 1, "Request Attachments (" + request.getAttachmentCount() + ")");
    579 			}
    580 			else if( evt.getPropertyName().equals( WsdlRequest.RESPONSE_PROPERTY ))
    581 			{
    582 				responseEditorTabs.setTitleAt( 1, "Response Attachments (" + (request.getResponse() == null ? 0 :
    583 					request.getResponse().getAttachments().length) + ")" );
    584 			}
    585 			else if( evt.getPropertyName().equals( WsdlRequest.REQUEST_HEADERS_PROPERTY ))
    586 			{
    587 				requestHeadersModel.setData( ( StringToStringMap ) evt.getNewValue() );
    588 			}
    589 		}
    590 	}
    591
    592 	public class WsdlRequestMessageEditor extends RequestMessageXmlEditor<WsdlRequest>
    593 	{
    594 		private InputAreaFocusListener inputAreaFocusListener;
    595 		private JXEditTextArea inputArea;
    596
    597 		public WsdlRequestMessageEditor(XmlDocument document)
    598 		{
    599 			super(document, request );
    600
    601 			XmlSourceEditorView editor = getSourceEditor();
    602 			inputArea = editor.getInputArea();
    603 			inputArea.getInputHandler().addKeyBinding("A+ENTER", submitButton.getAction());
    604 			inputArea.getInputHandler().addKeyBinding("A+X", cancelButton.getAction());
    605 			inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
    606 			inputArea.getInputHandler().addKeyBinding("F5", recreateButton.getAction());
    607 			inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
    608
    609 			inputAreaFocusListener = new InputAreaFocusListener();
    610 			inputArea.addFocusListener( inputAreaFocusListener);
    611 		}
    612
    613 		@Override
    614 		public void release()
    615 		{
    616 			super.release();
    617 			inputArea.removeFocusListener( inputAreaFocusListener );
    618 		}
    619 	}
    620
    621 	public class WsdlResponseMessageEditor extends ResponseMessageXmlEditor<WsdlRequest>
    622 	{
    623 		private JXEditTextArea inputArea;
    624 		private ResultAreaFocusListener resultAreaFocusListener;
    625
    626 		public WsdlResponseMessageEditor(XmlDocument document)
    627 		{
    628 			super(document, request );
    629
    630 			XmlSourceEditorView editor = getSourceEditor();
    631
    632 			inputArea = editor.getInputArea();
    633 			resultAreaFocusListener = new ResultAreaFocusListener();
    634 			inputArea.addFocusListener(resultAreaFocusListener);
    635
    636 			inputArea.getInputHandler().addKeyBinding("A+ENTER", submitButton.getAction());
    637 			inputArea.getInputHandler().addKeyBinding("A+X", cancelButton.getAction());
    638 			inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
    639 			inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
    640
    641 			JPopupMenu inputPopup = editor.getEditorPopup();
    642 			inputPopup.insert( new JSeparator(), 2 );
    643 			inputPopup.insert( wsiValidateAction, 3 );
    644 		}
    645
    646 		@Override
    647 		public void release()
    648 		{
    649 			super.release();
    650
    651 			inputArea.removeFocusListener( resultAreaFocusListener );
    652 		}
    653 	}
    654
    655 	protected final class InputAreaFocusListener implements FocusListener
    656 	{
    657 		public void focusGained(FocusEvent e)
    658 		{
    659 			responseHasFocus = false;
    660
    661 			statusBar.setTarget( requestEditor.getSourceEditor().getInputArea() );
    662 			if( !splitButton.isEnabled() )
    663 			{
    664 				requestTabs.setSelectedIndex( 0 );
    665 				return;
    666 			}
    667
    668 			if (getModelItem().getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
    669 				return;
    670
    671 			// dont resize if split has been dragged
    672 			if (((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged())
    673 				return;
    674
    675 			int pos = requestSplitPane.getDividerLocation();
    676 			if (pos >= 600)
    677 				return;
    678 			if (requestSplitPane.getMaximumDividerLocation() > 700)
    679 				requestSplitPane.setDividerLocation(600);
    680 			else
    681 				requestSplitPane.setDividerLocation(0.8);
    682 		}
    683
    684 		public void focusLost(FocusEvent e)
    685 		{
    686 		}
    687 	}
    688
    689 	protected final class ResultAreaFocusListener implements FocusListener
    690 	{
    691 		public void focusGained(FocusEvent e)
    692 		{
    693 			responseHasFocus = true;
    694
    695 			statusBar.setTarget( responseEditor.getSourceEditor().getInputArea() );
    696 			if( !splitButton.isEnabled() )
    697 			{
    698 				requestTabs.setSelectedIndex( 1 );
    699 				return;
    700 			}
    701
    702 			if (request.getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
    703 				return;
    704
    705 			// dont resize if split has been dragged or result is empty
    706 			if (((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged() || request.getResponse() == null)
    707 				return;
    708
    709 			int pos = requestSplitPane.getDividerLocation();
    710 			int maximumDividerLocation = requestSplitPane.getMaximumDividerLocation();
    711 			if (pos + 600 < maximumDividerLocation)
    712 				return;
    713
    714 			if (maximumDividerLocation > 700)
    715 				requestSplitPane.setDividerLocation(maximumDividerLocation - 600);
    716 			else
    717 				requestSplitPane.setDividerLocation(0.2);
    718 		}
    719
    720 		public void focusLost(FocusEvent e)
    721 		{
    722 		}
    723 	}
    724
    725 	public class SubmitAction extends AbstractAction
    726 	{
    727 		public SubmitAction()
    728 		{
    729 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/submit_request.gif"));
    730 			putValue(Action.SHORT_DESCRIPTION, "Submit request to specified endpoint URL");
    731 			putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt ENTER" ));
    732 		}
    733
    734 		public void actionPerformed(ActionEvent e)
    735 		{
    736 			if (submit != null && submit.getStatus() == Submit.Status.RUNNING)
    737 			{
    738 				if (UISupport.confirm("Cancel current request?", "Submit Request"))
    739 				{
    740 					submit.cancel();
    741 				}
    742 				else
    743 					return;
    744 			}
    745
    746 			try
    747 			{
    748 				submit = doSubmit();
    749 			}
    750 			catch (SubmitException e1)
    751 			{
    752 				SoapUI.logError( e1 );
    753 			}
    754 		}
    755 	}
    756
    757 	protected Submit doSubmit() throws SubmitException
    758 	{
    759 		return request.submit(new WsdlSubmitContext(null), true);
    760 	}
    761
    762 	private class CancelAction extends AbstractAction
    763 	{
    764 		public CancelAction()
    765 		{
    766 			super();
    767 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/cancel_request.gif"));
    768 			putValue(Action.SHORT_DESCRIPTION, "Aborts ongoing request");
    769 			putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt X" ));
    770 		}
    771
    772 		public void actionPerformed(ActionEvent e)
    773 		{
    774 			if (submit == null)
    775 				return;
    776
    777 			cancelButton.setEnabled(false);
    778 			submit.cancel();
    779 			setEnabled(true);
    780 			submit = null;
    781 		}
    782 	}
    783
    784 	private class ClosePanelAction extends AbstractAction
    785 	{
    786 		public void actionPerformed(ActionEvent e)
    787 		{
    788 			SoapUI.getDesktop().closeDesktopPanel(getModelItem());
    789 		}
    790 	}
    791
    792 	private class MoveFocusAction extends AbstractAction
    793 	{
    794 		public void actionPerformed(ActionEvent e)
    795 		{
    796 			if (requestEditor.hasFocus())
    797 			{
    798 				responseEditor.requestFocus();
    799 			}
    800 			else
    801 			{
    802 				requestEditor.requestFocus();
    803 			}
    804 		}
    805 	}
    806
    807 	protected class InternalSubmitListener implements SubmitListener
    808 	{
    809 		protected InternalSubmitListener()
    810 		{
    811 		}
    812
    813 		public boolean beforeSubmit(Submit submit, SubmitContext context)
    814 		{
    815 			if (submit.getRequest() != request )
    816 				return true;
    817
    818 			if( getModelItem().getSettings().getBoolean( UISettings.AUTO_VALIDATE_REQUEST ))
    819 			{
    820 				boolean result = requestEditor.saveDocument( true );
    821 				if( !result &&  getModelItem().getSettings().getBoolean( UISettings.ABORT_ON_INVALID_REQUEST ))
    822 				{
    823 					statusBar.setInfo( "Cancelled request due to invalid content" );
    824 					return false;
    825 				}
    826 			}
    827 			else requestEditor.saveDocument( false );
    828
    829 			setEnabled( false );
    830 			cancelButton.setEnabled( AbstractWsdlRequestDesktopPanel.this.submit != null );
    831 			wsiValidateAction.setEnabled( false );
    832 			return true;
    833 		}
    834
    835 		public void afterSubmit(Submit submit, SubmitContext context)
    836 		{
    837 			if (submit.getRequest() != request )
    838 				return;
    839
    840 			Status status = submit.getStatus();
    841 			WsdlResponse response = (WsdlResponse) submit.getResponse();
    842 			if (status != Status.CANCELED )
    843 			{
    844 				request.setResponse(response, context);
    845 			}
    846
    847 			cancelButton.setEnabled(false);
    848 			wsiValidateAction.setEnabled( request.getResponse() != null );
    849 			setEnabled(true);
    850
    851 			String message = null;
    852 			String infoMessage = null;
    853 			String requestName = request.getOperation().getInterface().getName() + "."
    854 					+ request.getOperation().getName() + ":" + request.getName();
    855
    856 			if (status == Status.CANCELED)
    857 			{
    858 				message = "CANCELED";
    859 				infoMessage = "[" + requestName + "] - CANCELED";
    860 			}
    861 			else
    862 			{
    863 				if (status == Status.ERROR || response == null)
    864 				{
    865 					message = "Error getting response; " + submit.getError();
    866 					infoMessage = "Error getting response for [" + requestName + "]; " + submit.getError();
    867 				}
    868 				else
    869 				{
    870 					message = "response time: " + response.getTimeTaken() + "ms (" + response.getContentLength() + " bytes)";
    871 					infoMessage = "Got response for [" + requestName + "] in " + response.getTimeTaken() + "ms ("
    872 							+ response.getContentLength() + " bytes)";
    873
    874 					if( !splitButton.isEnabled() )
    875 						requestTabs.setSelectedIndex( 1 );
    876
    877 					responseEditor.requestFocus();
    878 				}
    879
    880 				responseHeadersModel.setData( submit.getResponse() == null ? null : submit.getResponse().getResponseHeaders());
    881
    882 				updateSSLInfo( response == null ? null : response.getSSLInfo() );
    883 				wsiValidateAction.setEnabled( true );
    884 			}
    885
    886 			logMessages(message, infoMessage);
    887
    888 			if( getModelItem().getSettings().getBoolean( UISettings.AUTO_VALIDATE_RESPONSE ))
    889 				responseEditor.getSourceEditor().validate();
    890
    891 			AbstractWsdlRequestDesktopPanel.this.submit = null;
    892 		}
    893
    894 		protected void logMessages(String message, String infoMessage)
    895 		{
    896 			log.info(infoMessage);
    897 			statusBar.setInfo(message);
    898 		}
    899 	}
    900
    901 	public boolean onClose(boolean canCancel)
    902 	{
    903 		if (canCancel)
    904 		{
    905 			if (submit != null && submit.getStatus() == Submit.Status.RUNNING)
    906 			{
    907 				Boolean retVal = UISupport.confirmOrCancel("Cancel request before closing?", "Closing window");
    908 				if (retVal == null)
    909 					return false;
    910
    911 				if (retVal.booleanValue() && submit.getStatus() == Submit.Status.RUNNING)
    912 					submit.cancel();
    913 			}
    914 		}
    915 		else if (submit != null && submit.getStatus() == Submit.Status.RUNNING)
    916 		{
    917 			submit.cancel();
    918 		}
    919
    920 		request.removeSubmitListener( internalSubmitListener );
    921 		request.removePropertyChangeListener( attachmentsPropertyChangeListener );
    922 		endpointsModel.release();
    923
    924 		requestEditor.saveDocument( false );
    925 		requestEditor.release();
    926 		responseEditor.release();
    927
    928 		requestAttachmentPanel.release();
    929 		responseAttachmentPanel.release();
    930
    931 		responseEditor.getParent().remove( responseEditor );
    932 		responseEditorTabs.removeAll();
    933 		requestEditor.getParent().remove( requestEditor );
    934 		requestEditorTabs.removeAll();
    935 		requestSplitPane.removeAll();
    936 		sslInfoPane.getParent().remove( sslInfoPane );
    937
    938 		return super.release();
    939 	}
    940
    941 	public boolean dependsOn(ModelItem modelItem)
    942 	{
    943 		return modelItem == request || modelItem == request.getOperation()
    944 				|| modelItem == request.getOperation().getInterface()
    945 				|| modelItem == request.getOperation().getInterface().getProject();
    946 	}
    947
    948 	public String getDescription()
    949 	{
    950 		return "Request: [" + request.getName() + "] - " + request.getOperation().getInterface().getName() +
    951 		    "#" + request.getOperation().getName();
    952 	}
    953
    954 	private final class ChangeToTabsAction extends AbstractAction
    955 	{
    956 		public ChangeToTabsAction()
    957 		{
    958 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/toggle_tabs.gif"));
    959 			putValue(Action.SHORT_DESCRIPTION, "Toggles to tab-based layout");
    960 		}
    961
    962 		public void actionPerformed(ActionEvent e)
    963 		{
    964 			if( splitButton.isEnabled() )
    965 			{
    966 				splitButton.setEnabled( false );
    967 				removeContent( requestSplitPane );
    968 				setContent( requestTabPanel );
    969 				requestTabs.addTab( "Request", requestEditorTabPanel );
    970 				requestTabs.addTab( "Response", responseEditorTabPanel );
    971
    972 				if( responseHasFocus )
    973 				{
    974 					requestTabs.setSelectedIndex( 1 );
    975 					requestEditorTabs.requestFocus();
    976 				}
    977 				else
    978 				{
    979 					responseEditorTabs.requestFocus();
    980 				}
    981 			}
    982 			else
    983 			{
    984 				int selectedIndex = requestTabs.getSelectedIndex();
    985
    986 				splitButton.setEnabled( true );
    987 				removeContent( requestTabPanel );
    988 				setContent( requestSplitPane );
    989 				requestSplitPane.setTopComponent(requestEditorTabPanel);
    990 		   	requestSplitPane.setBottomComponent(responseEditorTabPanel);
    991 		   	requestSplitPane.setDividerLocation(0.5);
    992
    993 		   	if( selectedIndex == 0 )
    994 		   		requestEditor.requestFocus();
    995 		   	else
    996 		   		responseEditor.requestFocus();
    997 			}
    998
    999 			revalidate();
    1000 		}
    1001 	}
    1002
    1003 	public void setContent(JComponent content)
    1004 	{
    1005 		add( content, BorderLayout.CENTER );
    1006 	}
    1007
    1008 	public void removeContent(JComponent content)
    1009 	{
    1010 		remove( content );
    1011 	}
    1012 }