/* * 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.config.GotoConditionConfig; import com.eviware.soapui.config.GotoConditionTypeConfig; import com.eviware.soapui.config.GotoStepConfig; import com.eviware.soapui.config.TestStepConfig; import com.eviware.soapui.impl.support.http.HttpRequestTestStep; import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase; import com.eviware.soapui.model.propertyexpansion.PropertyExpander; import com.eviware.soapui.model.propertyexpansion.PropertyExpansion; import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer; import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils; import com.eviware.soapui.model.support.XPathReference; import com.eviware.soapui.model.support.XPathReferenceContainer; import com.eviware.soapui.model.support.XPathReferenceImpl; import com.eviware.soapui.model.testsuite.SamplerTestStep; 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.TestStep; import com.eviware.soapui.model.testsuite.TestStepResult; import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus; import com.eviware.soapui.support.StringUtils; import com.eviware.soapui.support.UISupport; import com.eviware.soapui.support.xml.XmlUtils; import org.apache.log4j.Logger; import org.apache.xmlbeans.XmlBoolean; import org.apache.xmlbeans.XmlObject; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.List; /** * TestStep that moves execution to another step based on the contents of a XML * Property * * @author ole.matzura */ public class WsdlGotoTestStep extends WsdlTestStepWithProperties implements XPathReferenceContainer, PropertyExpansionContainer { private GotoStepConfig gotoStepConfig; private List<GotoCondition> conditions = new ArrayList<GotoCondition>(); private boolean canceled; private final static Logger log = Logger.getLogger(WsdlGotoTestStep.class); public WsdlGotoTestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest) { super(testCase, config, true, forLoadTest); if (!forLoadTest) { setIcon(UISupport.createImageIcon("/conditional_goto_step.png")); } } @Override public void afterLoad() { TestStepConfig config = getConfig(); if (config.getConfig() == null) { gotoStepConfig = (GotoStepConfig) config.addNewConfig().changeType(GotoStepConfig.type); } else { gotoStepConfig = (GotoStepConfig) config.getConfig().changeType(GotoStepConfig.type); for (int c = 0; c < gotoStepConfig.sizeOfConditionArray(); c++) { conditions.add(new GotoCondition(gotoStepConfig.getConditionArray(c))); } } super.afterLoad(); } public void resetConfigOnMove(TestStepConfig config) { super.resetConfigOnMove(config); gotoStepConfig = (GotoStepConfig) config.getConfig().changeType(GotoStepConfig.type); for (int c = 0; c < gotoStepConfig.sizeOfConditionArray(); c++) { conditions.get(c).setConfig(gotoStepConfig.getConditionArray(c)); } } public TestStepResult run(TestCaseRunner runner, TestCaseRunContext context) { WsdlTestStepResult result = new WsdlTestStepResult(this); canceled = false; result.startTimer(); SamplerTestStep previousStep = getTestCase().findPreviousStepOfType(this, SamplerTestStep.class); if (previousStep == null) { result.stopTimer(); result.addMessage("Failed to find previous request step from [" + getName() + "]"); result.setStatus(TestStepStatus.FAILED); return result; } GotoCondition target = runConditions(previousStep, context); if (target == null) { result.addMessage("Missing matching condition, moving on."); } else { String targetStepName = target.getTargetStep().trim(); result.addMessage("Matched condition [" + targetStepName + "], transferring to [" + targetStepName + "]"); runner.gotoStep(runner.getTestCase().getTestStepIndexByName(targetStepName)); } result.stopTimer(); result.setStatus(TestStepStatus.OK); return result; } public GotoCondition runConditions(SamplerTestStep previousStep, TestCaseRunContext context) { for (GotoCondition condition : conditions) { if (canceled) { break; } try { if (condition.evaluate(previousStep, context)) { return condition; } } catch (Exception e) { log.error("Error making condition " + condition.getName() + "; " + e); } } return null; } public boolean cancel() { canceled = true; return canceled; } public int getConditionCount() { return conditions.size(); } public GotoCondition getConditionAt(int index) { return conditions.get(index); } public GotoCondition addCondition(String name) { GotoCondition condition = new GotoCondition(gotoStepConfig.addNewCondition()); condition.setName(name); condition.setType(GotoConditionTypeConfig.XPATH.toString()); conditions.add(condition); return condition; } public void removeConditionAt(int index) { conditions.remove(index); gotoStepConfig.removeCondition(index); } public void release() { super.release(); for (GotoCondition condition : conditions) { condition.release(); } } public class GotoCondition implements PropertyChangeListener { public final static String TARGET_STEP_PROPERTY = "target_step"; private GotoConditionConfig conditionConfig; private TestStep currentStep; private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); public GotoCondition(GotoConditionConfig conditionConfig) { this.conditionConfig = conditionConfig; initListeners(); } public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(propertyName, listener); } public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener(propertyName, listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener(listener); } private void initListeners() { release(); if (getTargetStep() != null) { int index = getTestCase().getTestStepIndexByName(getTargetStep()); if (index != -1) { currentStep = getTestCase().getTestStepAt(index); currentStep.addPropertyChangeListener(TestStep.NAME_PROPERTY, this); } } } public void release() { if (currentStep != null) { currentStep.removePropertyChangeListener(this); } } public boolean evaluate(SamplerTestStep previousStep, TestCaseRunContext context) throws Exception { if (getExpression() == null || getExpression().trim().length() == 0) { throw new Exception("Missing expression in condition [" + getName() + "]"); } if (getTargetStep() == null || getTargetStep().trim().length() == 0) { throw new Exception("Missing target step in condition [" + getName() + "]"); } if (getType().equals(GotoConditionTypeConfig.XPATH.toString())) { TestRequest testRequest = previousStep.getTestRequest(); // XmlObject xmlObject = XmlObject.Factory.parse( // testRequest.getResponse().getContentAsXml() ); XmlObject xmlObject = XmlUtils.createXmlObject(testRequest.getResponse().getContentAsXml()); String expression = PropertyExpander.expandProperties(context, getExpression()); XmlObject[] selectPath = xmlObject.selectPath(expression); if (selectPath.length == 1 && selectPath[0] instanceof XmlBoolean) { if (((XmlBoolean) selectPath[0]).getBooleanValue()) { return true; } } } else { log.error("Unkown condition type: " + getType()); } return false; } protected void setConfig(GotoConditionConfig conditionConfig) { this.conditionConfig = conditionConfig; } public String getType() { return conditionConfig.getType(); } public String getName() { return conditionConfig.getName(); } public String getExpression() { return conditionConfig.getExpression(); } public String getTargetStep() { return conditionConfig.getTargetStep(); } public void setType(String type) { conditionConfig.setType(type); } public void setName(String name) { conditionConfig.setName(name); } public void setExpression(String expression) { conditionConfig.setExpression(expression); } public void setTargetStep(String targetStep) { String oldStep = getTargetStep(); conditionConfig.setTargetStep(targetStep); initListeners(); propertyChangeSupport.firePropertyChange(TARGET_STEP_PROPERTY, oldStep, targetStep); } public void propertyChange(PropertyChangeEvent evt) { conditionConfig.setTargetStep(evt.getNewValue().toString()); propertyChangeSupport.firePropertyChange(TARGET_STEP_PROPERTY, evt.getOldValue(), evt.getNewValue()); } public TestProperty getSourceProperty() { HttpRequestTestStep previousStep = (HttpRequestTestStep) getTestCase().findPreviousStepOfType( WsdlGotoTestStep.this, HttpRequestTestStep.class); return previousStep == null ? null : previousStep.getProperty("Response"); } } public boolean hasProperties() { return false; } public PropertyExpansion[] getPropertyExpansions() { List<PropertyExpansion> result = new ArrayList<PropertyExpansion>(); for (GotoCondition condition : conditions) { result.addAll(PropertyExpansionUtils.extractPropertyExpansions(this, condition, "expression")); } return result.toArray(new PropertyExpansion[result.size()]); } public XPathReference[] getXPathReferences() { List<XPathReference> result = new ArrayList<XPathReference>(); for (GotoCondition condition : conditions) { if (StringUtils.hasContent(condition.getExpression())) { result.add(new XPathReferenceImpl("Condition for " + condition.getName() + " GotoCondition in " + getName(), condition.getSourceProperty(), condition, "expression")); } } return result.toArray(new XPathReference[result.size()]); } }