/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.wsdl.teststeps; import com.eviware.soapui.SoapUI; import com.eviware.soapui.config.JdbcRequestTestStepConfig; import com.eviware.soapui.config.TestAssertionConfig; import com.eviware.soapui.config.TestStepConfig; import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder; import com.eviware.soapui.impl.wsdl.panels.teststeps.JdbcRequest; import com.eviware.soapui.impl.wsdl.panels.teststeps.JdbcResponse; import com.eviware.soapui.impl.wsdl.panels.teststeps.JdbcSubmit; import com.eviware.soapui.impl.wsdl.support.JdbcMessageExchange; import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder; import com.eviware.soapui.impl.wsdl.support.assertions.AssertableConfig; import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer; import com.eviware.soapui.impl.wsdl.support.assertions.AssertionsSupport; import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase; import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext; import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry.AssertableType; import com.eviware.soapui.model.iface.Interface; import com.eviware.soapui.model.iface.Request.SubmitException; import com.eviware.soapui.model.iface.Submit; import com.eviware.soapui.model.iface.SubmitContext; import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils; import com.eviware.soapui.model.support.TestStepBeanProperty; 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.SamplerTestStep; 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.TestProperty; import com.eviware.soapui.model.testsuite.TestPropertyListener; import com.eviware.soapui.model.testsuite.TestStep; import com.eviware.soapui.model.testsuite.TestStepResult; import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus; import com.eviware.soapui.support.StringUtils; import org.apache.log4j.Logger; import org.apache.xmlbeans.SchemaType; import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl; import javax.swing.ImageIcon; import javax.xml.namespace.QName; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * WsdlTestStep that executes a WsdlTestRequest * * @author dragica.soldo */ public class JdbcRequestTestStep extends WsdlTestStepWithProperties implements Assertable, MutableTestPropertyHolder, PropertyChangeListener, SamplerTestStep { @SuppressWarnings("unused") private final static Logger log = Logger.getLogger(WsdlTestRequestStep.class); public final static String JDBCREQUEST = JdbcRequestTestStep.class.getName() + "@jdbcrequest"; public static final String STATUS_PROPERTY = WsdlTestRequest.class.getName() + "@status"; public static final String RESPONSE_PROPERTY = "response"; protected static final String DRIVER_FIELD = "Driver"; protected static final String CONNSTR_FIELD = "Connection String"; protected static final String PASS_FIELD = "Password"; public static final String PASS_TEMPLATE = "PASS_VALUE"; public static final String QUERY_FIELD = "SQL Query"; protected static final String STOREDPROCEDURE_FIELD = "Stored Procedure"; protected static final String DATA_CONNECTION_FIELD = "Connection"; protected static final String QUERY_ELEMENT = "query"; protected static final String STOREDPROCEDURE_ELEMENT = "stored-procedure"; private AssertionsSupport assertionsSupport; private PropertyChangeNotifier notifier; private XmlBeansPropertiesTestPropertyHolder propertyHolderSupport; private JdbcRequestTestStepConfig jdbcRequestTestStepConfig; private JdbcRequest jdbcRequest; private JdbcSubmit submit; public JdbcRequestTestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest) { super(testCase, config, true, forLoadTest); if (getConfig().getConfig() != null) { jdbcRequestTestStepConfig = (JdbcRequestTestStepConfig) getConfig().getConfig().changeType( JdbcRequestTestStepConfig.type); } else { jdbcRequestTestStepConfig = (JdbcRequestTestStepConfig) getConfig().addNewConfig().changeType( JdbcRequestTestStepConfig.type); } if (jdbcRequestTestStepConfig.getProperties() == null) { jdbcRequestTestStepConfig.addNewProperties(); } if (!jdbcRequestTestStepConfig.isSetConvertColumnNamesToUpperCase()) { jdbcRequestTestStepConfig.setConvertColumnNamesToUpperCase(true); } jdbcRequest = new JdbcRequest(this, forLoadTest); propertyHolderSupport = new XmlBeansPropertiesTestPropertyHolder(this, jdbcRequestTestStepConfig.getProperties()); addResponseAsXmlVirtualProperty(); initAssertions(); } private void addResponseAsXmlVirtualProperty() { TestStepBeanProperty responseProperty = new TestStepBeanProperty(WsdlTestStepWithProperties.RESPONSE_AS_XML, true, this, "responseContent", this) { @Override public String getDefaultValue() { return "</no-response>"; } @Override public QName getType() { return getSchemaType().getName(); } @Override public SchemaType getSchemaType() { return XmlAnyTypeImpl.type; } }; propertyHolderSupport.addVirtualProperty(WsdlTestStepWithProperties.RESPONSE_AS_XML, responseProperty); } @Override public void addTestPropertyListener(TestPropertyListener listener) { propertyHolderSupport.addTestPropertyListener(listener); } @Override public void removeTestPropertyListener(TestPropertyListener listener) { propertyHolderSupport.removeTestPropertyListener(listener); } public JdbcRequestTestStepConfig getJdbcRequestTestStepConfig() { return jdbcRequestTestStepConfig; } @Override public void resetConfigOnMove(TestStepConfig config) { super.resetConfigOnMove(config); jdbcRequestTestStepConfig = (JdbcRequestTestStepConfig) config.getConfig().changeType( JdbcRequestTestStepConfig.type); propertyHolderSupport.resetPropertiesConfig(jdbcRequestTestStepConfig.getProperties()); // addResponseAsXmlVirtualProperty(); assertionsSupport.refresh(); } @Override public WsdlTestStep clone(WsdlTestCase targetTestCase, String name) { beforeSave(); TestStepConfig config = (TestStepConfig) getConfig().copy(); JdbcRequestTestStep result = (JdbcRequestTestStep) targetTestCase.addTestStep(config); return result; } @Override public void release() { super.release(); } public TestStepResult run(TestCaseRunner runner, TestCaseRunContext runContext) { JdbcTestStepResult testStepResult = new JdbcTestStepResult(this); testStepResult.startTimer(); runContext.setProperty(AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult); try { submit = jdbcRequest.submit(runContext, false); JdbcResponse response = submit.getResponse(); if (submit.getStatus() != Submit.Status.CANCELED) { if (submit.getStatus() == Submit.Status.ERROR) { testStepResult.setStatus(TestStepStatus.FAILED); testStepResult.addMessage(submit.getError().toString()); jdbcRequest.setResponse(null); } else if (response == null) { testStepResult.setStatus(TestStepStatus.FAILED); testStepResult.addMessage("Request is missing response"); jdbcRequest.setResponse(null); } else { runContext.setProperty(AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult); jdbcRequest.setResponse(response); testStepResult.setTimeTaken(response.getTimeTaken()); testStepResult.setSize(response.getContentLength()); switch (jdbcRequest.getAssertionStatus()) { case FAILED: testStepResult.setStatus(TestStepStatus.FAILED); break; case VALID: testStepResult.setStatus(TestStepStatus.OK); break; case UNKNOWN: testStepResult.setStatus(TestStepStatus.UNKNOWN); break; } testStepResult.setResponse(response, testStepResult.getStatus() != TestStepStatus.FAILED); } } else { testStepResult.setStatus(TestStepStatus.CANCELED); testStepResult.addMessage("Request was canceled"); } if (response != null) { testStepResult.setRequestContent(response.getRequestContent()); } else { testStepResult.setRequestContent(jdbcRequest.getRequestContent()); } testStepResult.stopTimer(); } catch (SubmitException e) { testStepResult.setStatus(TestStepStatus.FAILED); testStepResult.addMessage("SubmitException: " + e); testStepResult.stopTimer(); } finally { submit = null; } if (testStepResult.getStatus() != TestStepStatus.CANCELED) { assertResponse(runContext); AssertionStatus assertionStatus = jdbcRequest.getAssertionStatus(); switch (assertionStatus) { case FAILED: { testStepResult.setStatus(TestStepStatus.FAILED); if (getAssertionCount() == 0) { testStepResult.addMessage("Invalid/empty response"); } else { for (int c = 0; c < getAssertionCount(); c++) { TestAssertion assertion = getAssertionAt(c); AssertionError[] errors = assertion.getErrors(); if (errors != null) { for (AssertionError error : errors) { testStepResult.addMessage("[" + assertion.getName() + "] " + error.getMessage()); } } } } break; } // default : testStepResult.setStatus( TestStepStatus.OK ); break; } } if (isDiscardResponse() && !SoapUI.getDesktop().hasDesktopPanel(this)) { jdbcRequest.setResponse(null); } // FIXME This should not be hard coded // FIXME This should not fire if the response is the same. Could we implement a property changed event handler instead? firePropertyValueChanged("ResponseAsXml", null, testStepResult.getResponseContentAsXml()); return testStepResult; } @Override public boolean cancel() { if (submit == null) { return false; } submit.cancel(); return true; } @Override public String getDefaultSourcePropertyName() { return "Response"; } private void initAssertions() { assertionsSupport = new AssertionsSupport(this, new AssertableConfig() { public TestAssertionConfig addNewAssertion() { return getJdbcRequestTestStepConfig().addNewAssertion(); } public List<TestAssertionConfig> getAssertionList() { return getJdbcRequestTestStepConfig().getAssertionList(); } public void removeAssertion(int ix) { getJdbcRequestTestStepConfig().removeAssertion(ix); } public TestAssertionConfig insertAssertion(TestAssertionConfig source, int ix) { TestAssertionConfig conf = getJdbcRequestTestStepConfig().insertNewAssertion(ix); conf.set(source); return conf; } }); } private class PropertyChangeNotifier { private AssertionStatus oldStatus; private ImageIcon oldIcon; public PropertyChangeNotifier() { oldStatus = getAssertionStatus(); oldIcon = getIcon(); } public void notifyChange() { AssertionStatus newStatus = getAssertionStatus(); ImageIcon newIcon = getIcon(); if (oldStatus != newStatus) { notifyPropertyChanged(STATUS_PROPERTY, oldStatus, newStatus); } if (oldIcon != newIcon) { notifyPropertyChanged(ICON_PROPERTY, oldIcon, getIcon()); } oldStatus = newStatus; oldIcon = newIcon; } } public TestAssertion addAssertion(String assertionLabel) { PropertyChangeNotifier notifier = new PropertyChangeNotifier(); try { WsdlMessageAssertion assertion = assertionsSupport.addWsdlAssertion(assertionLabel); if (assertion == null) { return null; } if (getJdbcRequest().getResponse() != null) { assertion.assertResponse(new JdbcMessageExchange(this, getJdbcRequest().getResponse()), new WsdlTestRunContext(this)); notifier.notifyChange(); } return assertion; } catch (Exception e) { SoapUI.logError(e); return null; } } public void addAssertionsListener(AssertionsListener listener) { assertionsSupport.addAssertionsListener(listener); } public TestAssertion cloneAssertion(TestAssertion source, String name) { return assertionsSupport.cloneAssertion(source, name); } public String getAssertableContentAsXml() { return getAssertableContent(); } public String getAssertableContent() { TestProperty property = getProperty("ResponseAsXml"); String value = property.getValue(); return StringUtils.hasContent(value) ? value : property.getDefaultValue(); } public boolean isConvertColumnNamesToUpperCase() { return jdbcRequestTestStepConfig.getConvertColumnNamesToUpperCase(); } public String getResponseContent() { return getJdbcRequest().getResponse() == null ? "" : getJdbcRequest().getResponse().getContentAsString(); } public WsdlMessageAssertion importAssertion(WsdlMessageAssertion source, boolean overwrite, boolean createCopy, String newName) { return assertionsSupport.importAssertion(source, overwrite, createCopy, newName); } public AssertableType getAssertableType() { return AssertableType.RESPONSE; } public TestAssertion getAssertionAt(int c) { return assertionsSupport.getAssertionAt(c); } public TestAssertion getAssertionByName(String name) { return assertionsSupport.getAssertionByName(name); } public int getAssertionCount() { return assertionsSupport.getAssertionCount(); } public List<TestAssertion> getAssertionList() { return new ArrayList<TestAssertion>(assertionsSupport.getAssertionList()); } public void propertyChange(PropertyChangeEvent arg0) { if (arg0.getPropertyName().equals(TestAssertion.CONFIGURATION_PROPERTY) || arg0.getPropertyName().equals(TestAssertion.DISABLED_PROPERTY)) { if (getJdbcRequest().getResponse() != null) { assertResponse(new WsdlTestRunContext(this)); } } } public Map<String, TestAssertion> getAssertions() { return assertionsSupport.getAssertions(); } public String getDefaultAssertableContent() { return null; } public AssertionStatus getAssertionStatus() { return jdbcRequest.getAssertionStatus(); } @Override public ImageIcon getIcon() { return jdbcRequest.getIcon(); } public Interface getInterface() { return null; } public TestAssertion moveAssertion(int ix, int offset) { PropertyChangeNotifier notifier = new PropertyChangeNotifier(); TestAssertion assertion = getAssertionAt(ix); try { return assertionsSupport.moveAssertion(ix, offset); } finally { ((WsdlMessageAssertion) assertion).release(); notifier.notifyChange(); } } public void removeAssertion(TestAssertion assertion) { PropertyChangeNotifier notifier = new PropertyChangeNotifier(); try { assertionsSupport.removeAssertion((WsdlMessageAssertion) assertion); } finally { ((WsdlMessageAssertion) assertion).release(); notifier.notifyChange(); } } public void removeAssertionsListener(AssertionsListener listener) { assertionsSupport.removeAssertionsListener(listener); } public void assertResponse(SubmitContext context) { try { if (notifier == null) { notifier = new PropertyChangeNotifier(); } JdbcMessageExchange messageExchange = new JdbcMessageExchange(this, getJdbcRequest().getResponse()); if (getJdbcRequest().getResponse() != null) { // assert! for (WsdlMessageAssertion assertion : assertionsSupport.getAssertionList()) { assertion.assertResponse(messageExchange, context); } } notifier.notifyChange(); } catch (Exception e) { e.printStackTrace(); } } public TestProperty addProperty(String name) { return propertyHolderSupport.addProperty(name); } public TestProperty removeProperty(String propertyName) { return propertyHolderSupport.removeProperty(propertyName); } public void removeAllProperties() { for (String propertyName : propertyHolderSupport.getPropertyNames()) { propertyHolderSupport.removeProperty(propertyName); } } public boolean renameProperty(String name, String newName) { return PropertyExpansionUtils.renameProperty(propertyHolderSupport.getProperty(name), newName, getTestCase()) != null; } // FIXME Remove the overridden methods in TestPropertyHolder // public void addTestPropertyListener( TestPropertyListener listener ) // { // propertyHolderSupport.addTestPropertyListener( listener ); // } @Override public Map<String, TestProperty> getProperties() { return propertyHolderSupport.getProperties(); } @Override public TestProperty getProperty(String name) { return propertyHolderSupport.getProperty(name); } @Override public TestProperty getPropertyAt(int index) { return propertyHolderSupport.getPropertyAt(index); } @Override public int getPropertyCount() { return propertyHolderSupport.getPropertyCount(); } @Override public List<TestProperty> getPropertyList() { return propertyHolderSupport.getPropertyList(); } @Override public String[] getPropertyNames() { return propertyHolderSupport.getPropertyNames(); } @Override public String getPropertyValue(String name) { return propertyHolderSupport.getPropertyValue(name); } @Override public boolean hasProperty(String name) { return propertyHolderSupport.hasProperty(name); } @Override public void setPropertyValue(String name, String value) { propertyHolderSupport.setPropertyValue(name, value); } public void setPropertyValue(String name, Object value) { setPropertyValue(name, String.valueOf(value)); } @Override public void moveProperty(String propertyName, int targetIndex) { propertyHolderSupport.moveProperty(propertyName, targetIndex); } public String getDriver() { return jdbcRequestTestStepConfig.getDriver(); } public void setDriver(String d) { String old = getDriver(); jdbcRequestTestStepConfig.setDriver(d); notifyPropertyChanged("driver", old, d); } public String getConnectionString() { return jdbcRequestTestStepConfig.getConnectionString(); } public void setConnectionString(String c) { String old = getConnectionString(); jdbcRequestTestStepConfig.setConnectionString(c); notifyPropertyChanged("connectionString", old, c); } public String getQuery() { return jdbcRequestTestStepConfig.getQuery(); } public void setQuery(String q) { String old = getQuery(); jdbcRequestTestStepConfig.setQuery(q); notifyPropertyChanged("query", old, q); } public String getPassword() { return jdbcRequestTestStepConfig.getPassword(); } public void setPassword(String p) { String old = getPassword(); jdbcRequestTestStepConfig.setPassword(p); notifyPropertyChanged("password", old, p); } public static boolean isNeededPassword(String connStr) { return !StringUtils.isNullOrEmpty(connStr) ? connStr.contains(PASS_TEMPLATE) : false; } public boolean isStoredProcedure() { return jdbcRequestTestStepConfig.getStoredProcedure(); } public void setStoredProcedure(boolean sp) { String old = getPassword(); jdbcRequestTestStepConfig.setStoredProcedure(sp); notifyPropertyChanged("password", old, sp); } public void setConvertColumnNamesToUpperCase(boolean sp) { jdbcRequestTestStepConfig.setConvertColumnNamesToUpperCase(sp); } public JdbcRequest getJdbcRequest() { return jdbcRequest; } public String getQueryTimeout() { return jdbcRequestTestStepConfig.getQueryTimeout(); } public String getMaxRows() { return jdbcRequestTestStepConfig.getMaxRows(); } public String getFetchSize() { return jdbcRequestTestStepConfig.getFetchSize(); } public void setQueryTimeout(String queryTimeout) { String old = getQueryTimeout(); jdbcRequestTestStepConfig.setQueryTimeout(queryTimeout); notifyPropertyChanged("queryTimeout", old, queryTimeout); } public void setMaxRows(String maxRows) { String old = getMaxRows(); jdbcRequestTestStepConfig.setMaxRows(maxRows); notifyPropertyChanged("maxRows", old, maxRows); } public void setFetchSize(String fetchSize) { String old = getFetchSize(); jdbcRequestTestStepConfig.setFetchSize(fetchSize); notifyPropertyChanged("fetchSize", old, fetchSize); } public void setResponse(JdbcResponse response, SubmitContext context) { JdbcResponse oldResponse = jdbcRequest.getResponse(); jdbcRequest.setResponse(response); notifyPropertyChanged(RESPONSE_PROPERTY, oldResponse, response); assertResponse(context); } public boolean isDiscardResponse() { return jdbcRequest.isDiscardResponse(); } public void setDiscardResponse(boolean discardResponse) { jdbcRequest.setDiscardResponse(discardResponse); } public TestRequest getTestRequest() { return jdbcRequest; } public TestStep getTestStep() { return this; } @Override public void prepare(TestCaseRunner testRunner, TestCaseRunContext testRunContext) throws Exception { super.prepare(testRunner, testRunContext); setResponse(null, testRunContext); for (TestAssertion assertion : jdbcRequest.getAssertionList()) { assertion.prepare(testRunner, testRunContext); } } }