/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.impl.wsdl.panels.teststeps;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.Document;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.support.components.ModelItemXmlEditor;
import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
import com.eviware.soapui.impl.wsdl.mock.WsdlMockResult;
import com.eviware.soapui.impl.wsdl.panels.mockoperation.AbstractWsdlMockResponseDesktopPanel;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlMockResponseTestStep;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.support.TestRunListenerAdapter;
import com.eviware.soapui.model.testsuite.Assertable;
import com.eviware.soapui.model.testsuite.AssertionError;
import com.eviware.soapui.model.testsuite.AssertionsListener;
import com.eviware.soapui.model.testsuite.LoadTestRunner;
import com.eviware.soapui.model.testsuite.TestAssertion;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.monitor.support.TestMonitorListenerAdapter;
import com.eviware.soapui.security.SecurityTestRunner;
import com.eviware.soapui.support.DocumentListenerAdapter;
import com.eviware.soapui.support.ModelItemPropertyEditorModel;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.JComponentInspector;
import com.eviware.soapui.support.components.JInspectorPanel;
import com.eviware.soapui.support.components.JInspectorPanelFactory;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.xml.XmlUtils;
public class WsdlMockResponseStepDesktopPanel extends
AbstractWsdlMockResponseDesktopPanel<WsdlMockResponseTestStep, WsdlMockResponse>
{
private JTextArea logArea;
private AssertionsPanel assertionsPanel;
private JTextField portField;
private JTextField pathField;
private InternalTestRunListener testRunListener;
private InternalTestMonitorListener testMonitorListener = new InternalTestMonitorListener();
private InternalAssertionsListener assertionsListener = new InternalAssertionsListener();
private JInspectorPanel inspectorPanel;
private JComponentInspector<JComponent> assertionInspector;
private JComponentInspector<JComponent> logInspector;
private ModelItemPropertyEditorModel<WsdlMockResponseTestStep> queryEditorModel;
private ModelItemPropertyEditorModel<WsdlMockResponseTestStep> matchEditorModel;
public WsdlMockResponseStepDesktopPanel( WsdlMockResponseTestStep mockResponseStep )
{
super( mockResponseStep );
init( mockResponseStep.getMockResponse() );
testRunListener = new InternalTestRunListener();
mockResponseStep.getTestCase().addTestRunListener( testRunListener );
SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
setEnabled( !SoapUI.getTestMonitor().hasRunningTest( mockResponseStep.getTestCase() ) );
mockResponseStep.addAssertionsListener( assertionsListener );
}
@Override
protected JComponent buildContent()
{
inspectorPanel = JInspectorPanelFactory.build( super.buildContent() );
assertionsPanel = buildAssertionsPanel();
assertionInspector = new JComponentInspector<JComponent>( assertionsPanel, "Assertions ("
+ getModelItem().getAssertionCount() + ")", "Assertions for this Test Request", true );
inspectorPanel.addInspector( assertionInspector );
logInspector = new JComponentInspector<JComponent>( buildLogPanel(), "Request Log (0)", "Log of requests", true );
inspectorPanel.addInspector( logInspector );
inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildQueryMatchPanel(), "Query/Match",
"Query/Match configuration", true ) );
inspectorPanel.setDefaultDividerLocation( 0.6F );
inspectorPanel.setCurrentInspector( "Assertions" );
updateStatusIcon();
return inspectorPanel.getComponent();
}
private void updateStatusIcon()
{
Assertable.AssertionStatus status = getModelItem().getAssertionStatus();
switch( status )
{
case FAILED :
{
assertionInspector.setIcon( UISupport.createImageIcon( "/failed_assertion.gif" ) );
inspectorPanel.activate( assertionInspector );
break;
}
case UNKNOWN :
{
assertionInspector.setIcon( UISupport.createImageIcon( "/unknown_assertion.gif" ) );
break;
}
case VALID :
{
assertionInspector.setIcon( UISupport.createImageIcon( "/valid_assertion.gif" ) );
inspectorPanel.deactivate();
break;
}
}
}
private JComponent buildLogPanel()
{
logArea = new JTextArea();
logArea.setEditable( false );
logArea.setToolTipText( "Response Log" );
JPanel panel = new JPanel( new BorderLayout() );
panel.add( new JScrollPane( logArea ), BorderLayout.CENTER );
return panel;
}
public void setContent( JComponent content )
{
inspectorPanel.setContentComponent( content );
}
public void removeContent( JComponent content )
{
inspectorPanel.setContentComponent( null );
}
@Override
protected void createToolbar( JXToolBar toolbar )
{
toolbar.addUnrelatedGap();
toolbar.addFixed( new JLabel( "Path" ) );
toolbar.addRelatedGap();
pathField = new JTextField( getModelItem().getPath(), 15 );
pathField.getDocument().addDocumentListener( new DocumentListenerAdapter()
{
@Override
public void update( Document document )
{
getModelItem().setPath( pathField.getText() );
}
} );
toolbar.addFixed( pathField );
toolbar.addUnrelatedGap();
toolbar.addFixed( new JLabel( "Port" ) );
toolbar.addRelatedGap();
portField = new JTextField( String.valueOf( getModelItem().getPort() ), 5 );
portField.getDocument().addDocumentListener( new DocumentListenerAdapter()
{
@Override
public void update( Document document )
{
try
{
getModelItem().setPort( Integer.parseInt( portField.getText() ) );
}
catch( NumberFormatException e )
{
}
}
} );
toolbar.addFixed( portField );
}
private JComponent buildQueryMatchPanel()
{
JPanel panel = new JPanel( new BorderLayout() );
panel.add( buildQueryMatchToolbar(), BorderLayout.NORTH );
JSplitPane splitPane = UISupport.createHorizontalSplit( buildQueryEditor(), buildMatchEditor() );
panel.add( splitPane, BorderLayout.CENTER );
splitPane.setDividerLocation( 200 );
return panel;
}
private Component buildMatchEditor()
{
JPanel panel = new JPanel( new BorderLayout() );
matchEditorModel = new ModelItemPropertyEditorModel<WsdlMockResponseTestStep>( getModelItem(), "match" );
panel.add( UISupport.getEditorFactory().buildXmlEditor( matchEditorModel ), BorderLayout.CENTER );
UISupport.addTitledBorder( panel, "Matching Value" );
return panel;
}
private Component buildQueryEditor()
{
JPanel panel = new JPanel( new BorderLayout() );
queryEditorModel = new ModelItemPropertyEditorModel<WsdlMockResponseTestStep>( getModelItem(), "query" );
panel.add( UISupport.getEditorFactory().buildXPathEditor( queryEditorModel ), BorderLayout.CENTER );
UISupport.addTitledBorder( panel, "XPath Query" );
return panel;
}
protected JXToolBar buildQueryMatchToolbar()
{
JXToolBar toolBar = UISupport.createSmallToolbar();
toolBar.addFixed( new JButton( new SelectFromCurrentAction() ) );
return toolBar;
}
public class SelectFromCurrentAction extends AbstractAction
{
public SelectFromCurrentAction()
{
super( "Select from current" );
putValue( Action.SHORT_DESCRIPTION, "Selects the Query XPath expression from the last request Match field" );
}
public void actionPerformed( ActionEvent arg0 )
{
if( getModelItem().getLastResult() != null && getModelItem().getLastResult().getMockRequest() != null
&& StringUtils.hasContent( getModelItem().getQuery() ) )
{
getModelItem().setMatch(
XmlUtils.getXPathValue( getModelItem().getLastResult().getMockRequest().getRequestContent(),
PropertyExpander.expandProperties( getModelItem(), getModelItem().getQuery() ) ) );
}
}
}
private AssertionsPanel buildAssertionsPanel()
{
assertionsPanel = new AssertionsPanel( getModelItem() )
{
protected void selectError( AssertionError error )
{
ModelItemXmlEditor<?, ?> editor = getResponseEditor();
editor.requestFocus();
}
};
return assertionsPanel;
}
@Override
public boolean onClose( boolean canCancel )
{
getModelItem().getTestCase().removeTestRunListener( testRunListener );
SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
assertionsPanel.release();
queryEditorModel.release();
matchEditorModel.release();
inspectorPanel.release();
getModelItem().removeAssertionsListener( assertionsListener );
return super.onClose( canCancel );
}
public void setEnabled( boolean enabled )
{
super.setEnabled( enabled );
pathField.setEnabled( enabled );
portField.setEnabled( enabled );
}
public boolean dependsOn( ModelItem modelItem )
{
return modelItem == getModelItem() || modelItem == getModelItem().getTestCase()
|| modelItem == getModelItem().getOperation() || modelItem == getModelItem().getOperation().getInterface()
|| modelItem == getModelItem().getTestCase().getTestSuite()
|| modelItem == getModelItem().getTestCase().getTestSuite().getProject();
}
public class InternalTestRunListener extends TestRunListenerAdapter
{
@Override
public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
{
setEnabled( true );
}
@Override
public void beforeRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
{
setEnabled( false );
}
@Override
public void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep )
{
if( testStep == getModelItem() )
{
logArea.setText( logArea.getText() + new Date( System.currentTimeMillis() ).toString()
+ ": Waiting for request on http://127.0.0.1:" + getModelItem().getPort() + getModelItem().getPath()
+ "\r\n" );
}
}
@Override
public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result )
{
if( result.getTestStep() == getModelItem() )
{
String msg = new Date( result.getTimeStamp() ).toString() + ": Handled request in " + result.getTimeTaken()
+ "ms";
logArea.setText( logArea.getText() + msg + "\r\n" );
}
}
}
private class InternalTestMonitorListener extends TestMonitorListenerAdapter
{
public void loadTestFinished( LoadTestRunner runner )
{
setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
}
public void loadTestStarted( LoadTestRunner runner )
{
if( runner.getLoadTest().getTestCase() == getModelItem().getTestCase() )
setEnabled( false );
}
public void securityTestFinished( SecurityTestRunner runner )
{
setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
}
public void securityTestStarted( SecurityTestRunner runner )
{
if( runner.getSecurityTest().getTestCase() == getModelItem().getTestCase() )
setEnabled( false );
}
public void testCaseFinished( TestCaseRunner runner )
{
setEnabled( !SoapUI.getTestMonitor().hasRunningTest( getModelItem().getTestCase() ) );
}
public void testCaseStarted( TestCaseRunner runner )
{
if( runner.getTestCase() == getModelItem().getTestCase() )
setEnabled( false );
}
}
public void propertyChange( PropertyChangeEvent evt )
{
super.propertyChange( evt );
if( evt.getPropertyName().equals( WsdlMockResponseTestStep.STATUS_PROPERTY ) )
updateStatusIcon();
}
@SuppressWarnings( "unused" )
private final class DeclareNamespacesAction extends AbstractAction
{
public DeclareNamespacesAction()
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/declareNs.gif" ) );
putValue( Action.SHORT_DESCRIPTION,
"Declare available response/request namespaces in source/target expressions" );
}
public void actionPerformed( ActionEvent e )
{
try
{
WsdlMockResult lastResult = getMockResponse().getMockResult();
String content = null;
if( lastResult == null )
{
if( !UISupport.confirm( "Missing last result, declare from default request instead?",
"Declare Namespaces" ) )
{
return;
}
content = getMockResponse().getMockOperation().getOperation().createRequest( true );
}
else
{
content = lastResult.getMockRequest().getRequestContent();
}
String path = getModelItem().getQuery();
if( path == null )
path = "";
getModelItem().setQuery( XmlUtils.declareXPathNamespaces( content ) + path );
}
catch( Exception e1 )
{
UISupport.showErrorMessage( e1 );
}
}
}
private final class InternalAssertionsListener implements AssertionsListener
{
public void assertionAdded( TestAssertion assertion )
{
assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
}
public void assertionRemoved( TestAssertion assertion )
{
assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
}
public void assertionMoved( TestAssertion assertion, int ix, int offset )
{
assertionInspector.setTitle( "Assertions (" + getModelItem().getAssertionCount() + ")" );
}
}
}