1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.teststeps;
14
15 import java.beans.PropertyChangeEvent;
16 import java.beans.PropertyChangeListener;
17 import java.beans.PropertyChangeSupport;
18 import java.util.ArrayList;
19 import java.util.List;
20
21 import org.apache.log4j.Logger;
22 import org.apache.xmlbeans.XmlBoolean;
23 import org.apache.xmlbeans.XmlObject;
24
25 import com.eviware.soapui.config.GotoConditionConfig;
26 import com.eviware.soapui.config.GotoConditionTypeConfig;
27 import com.eviware.soapui.config.GotoStepConfig;
28 import com.eviware.soapui.config.TestStepConfig;
29 import com.eviware.soapui.impl.support.AbstractHttpRequest;
30 import com.eviware.soapui.impl.support.http.HttpRequestTestStep;
31 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
32 import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
33 import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
34 import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
35 import com.eviware.soapui.model.support.XPathReference;
36 import com.eviware.soapui.model.support.XPathReferenceContainer;
37 import com.eviware.soapui.model.support.XPathReferenceImpl;
38 import com.eviware.soapui.model.testsuite.TestCaseRunContext;
39 import com.eviware.soapui.model.testsuite.TestCaseRunner;
40 import com.eviware.soapui.model.testsuite.TestProperty;
41 import com.eviware.soapui.model.testsuite.TestStep;
42 import com.eviware.soapui.model.testsuite.TestStepResult;
43 import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
44 import com.eviware.soapui.support.StringUtils;
45 import com.eviware.soapui.support.UISupport;
46
47 /***
48 * TestStep that moves execution to another step based on the contents of a XML
49 * Property
50 *
51 * @author ole.matzura
52 */
53
54 public class WsdlGotoTestStep extends WsdlTestStepWithProperties implements XPathReferenceContainer
55 {
56 private GotoStepConfig gotoStepConfig;
57 private List<GotoCondition> conditions = new ArrayList<GotoCondition>();
58 private boolean canceled;
59
60 private final static Logger log = Logger.getLogger( WsdlGotoTestStep.class );
61
62 public WsdlGotoTestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
63 {
64 super( testCase, config, true, forLoadTest );
65
66 if( !forLoadTest )
67 {
68 setIcon( UISupport.createImageIcon( "/goto.gif" ) );
69 }
70 }
71
72 @Override
73 public void afterLoad()
74 {
75 TestStepConfig config = getConfig();
76
77 if( config.getConfig() == null )
78 {
79 gotoStepConfig = ( GotoStepConfig )config.addNewConfig().changeType( GotoStepConfig.type );
80 }
81 else
82 {
83 gotoStepConfig = ( GotoStepConfig )config.getConfig().changeType( GotoStepConfig.type );
84 for( int c = 0; c < gotoStepConfig.sizeOfConditionArray(); c++ )
85 {
86 conditions.add( new GotoCondition( gotoStepConfig.getConditionArray( c ) ) );
87 }
88 }
89
90 super.afterLoad();
91 }
92
93 public void resetConfigOnMove( TestStepConfig config )
94 {
95 super.resetConfigOnMove( config );
96
97 gotoStepConfig = ( GotoStepConfig )config.getConfig().changeType( GotoStepConfig.type );
98 for( int c = 0; c < gotoStepConfig.sizeOfConditionArray(); c++ )
99 {
100 conditions.get( c ).setConfig( gotoStepConfig.getConditionArray( c ) );
101 }
102 }
103
104 public TestStepResult run( TestCaseRunner runner, TestCaseRunContext context )
105 {
106 WsdlTestStepResult result = new WsdlTestStepResult( this );
107 canceled = false;
108
109 result.startTimer();
110
111 HttpRequestTestStep previousStep = getTestCase().findPreviousStepOfType( this, HttpRequestTestStep.class );
112
113 if( previousStep == null )
114 {
115 result.stopTimer();
116 result.addMessage( "Failed to find previous request step from [" + getName() + "]" );
117 result.setStatus( TestStepStatus.FAILED );
118 return result;
119 }
120
121 GotoCondition target = runConditions( previousStep, context );
122 if( target == null )
123 {
124 result.addMessage( "Missing matching condition, moving on." );
125 }
126 else
127 {
128 String targetStepName = target.getTargetStep().trim();
129 result.addMessage( "Matched condition [" + targetStepName + "], transferring to [" + targetStepName + "]" );
130 runner.gotoStep( runner.getTestCase().getTestStepIndexByName( targetStepName ) );
131 }
132
133 result.stopTimer();
134 result.setStatus( TestStepStatus.OK );
135 return result;
136 }
137
138 public GotoCondition runConditions( HttpRequestTestStep previousStep, TestCaseRunContext context )
139 {
140 for( GotoCondition condition : conditions )
141 {
142 if( canceled )
143 break;
144
145 try
146 {
147 if( condition.evaluate( previousStep, context ) )
148 {
149 return condition;
150 }
151 }
152 catch( Exception e )
153 {
154 log.error( "Error making condition " + condition.getName() + "; " + e );
155 }
156 }
157
158 return null;
159 }
160
161 public boolean cancel()
162 {
163 canceled = true;
164 return canceled;
165 }
166
167 public int getConditionCount()
168 {
169 return conditions.size();
170 }
171
172 public GotoCondition getConditionAt( int index )
173 {
174 return conditions.get( index );
175 }
176
177 public GotoCondition addCondition( String name )
178 {
179 GotoCondition condition = new GotoCondition( gotoStepConfig.addNewCondition() );
180 condition.setName( name );
181 condition.setType( GotoConditionTypeConfig.XPATH.toString() );
182 conditions.add( condition );
183 return condition;
184 }
185
186 public void removeConditionAt( int index )
187 {
188 conditions.remove( index );
189 gotoStepConfig.removeCondition( index );
190 }
191
192 public void release()
193 {
194 super.release();
195
196 for( GotoCondition condition : conditions )
197 {
198 condition.release();
199 }
200 }
201
202 public class GotoCondition implements PropertyChangeListener
203 {
204 public final static String TARGET_STEP_PROPERTY = "target_step";
205
206 private GotoConditionConfig conditionConfig;
207 private TestStep currentStep;
208 private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( this );
209
210 public GotoCondition( GotoConditionConfig conditionConfig )
211 {
212 this.conditionConfig = conditionConfig;
213 initListeners();
214 }
215
216 public void addPropertyChangeListener( String propertyName, PropertyChangeListener listener )
217 {
218 propertyChangeSupport.addPropertyChangeListener( propertyName, listener );
219 }
220
221 public void addPropertyChangeListener( PropertyChangeListener listener )
222 {
223 propertyChangeSupport.addPropertyChangeListener( listener );
224 }
225
226 public void removePropertyChangeListener( String propertyName, PropertyChangeListener listener )
227 {
228 propertyChangeSupport.removePropertyChangeListener( propertyName, listener );
229 }
230
231 public void removePropertyChangeListener( PropertyChangeListener listener )
232 {
233 propertyChangeSupport.removePropertyChangeListener( listener );
234 }
235
236 private void initListeners()
237 {
238 release();
239
240 if( getTargetStep() != null )
241 {
242 int index = getTestCase().getTestStepIndexByName( getTargetStep() );
243 if( index != -1 )
244 {
245 currentStep = getTestCase().getTestStepAt( index );
246 currentStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, this );
247 }
248 }
249 }
250
251 public void release()
252 {
253 if( currentStep != null )
254 currentStep.removePropertyChangeListener( this );
255 }
256
257 public boolean evaluate( HttpRequestTestStep previousStep, TestCaseRunContext context ) throws Exception
258 {
259 if( getExpression() == null || getExpression().trim().length() == 0 )
260 throw new Exception( "Missing expression in condition [" + getName() + "]" );
261
262 if( getTargetStep() == null || getTargetStep().trim().length() == 0 )
263 throw new Exception( "Missing target step in condition [" + getName() + "]" );
264
265 if( getType().equals( GotoConditionTypeConfig.XPATH.toString() ) )
266 {
267 AbstractHttpRequest<?> testRequest = previousStep.getHttpRequest();
268 XmlObject xmlObject = XmlObject.Factory.parse( testRequest.getResponse().getContentAsXml() );
269
270 String expression = PropertyExpander.expandProperties( context, getExpression() );
271 XmlObject[] selectPath = xmlObject.selectPath( expression );
272 if( selectPath.length == 1 && selectPath[0] instanceof XmlBoolean )
273 {
274 if( ( ( XmlBoolean )selectPath[0] ).getBooleanValue() )
275 {
276 return true;
277 }
278 }
279 }
280 else
281 {
282 log.error( "Unkown condition type: " + getType() );
283 }
284
285 return false;
286 }
287
288 protected void setConfig( GotoConditionConfig conditionConfig )
289 {
290 this.conditionConfig = conditionConfig;
291 }
292
293 public String getType()
294 {
295 return conditionConfig.getType();
296 }
297
298 public String getName()
299 {
300 return conditionConfig.getName();
301 }
302
303 public String getExpression()
304 {
305 return conditionConfig.getExpression();
306 }
307
308 public String getTargetStep()
309 {
310 return conditionConfig.getTargetStep();
311 }
312
313 public void setType( String type )
314 {
315 conditionConfig.setType( type );
316 }
317
318 public void setName( String name )
319 {
320 conditionConfig.setName( name );
321 }
322
323 public void setExpression( String expression )
324 {
325 conditionConfig.setExpression( expression );
326 }
327
328 public void setTargetStep( String targetStep )
329 {
330 String oldStep = getTargetStep();
331 conditionConfig.setTargetStep( targetStep );
332 initListeners();
333 propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, oldStep, targetStep );
334 }
335
336 public void propertyChange( PropertyChangeEvent evt )
337 {
338 conditionConfig.setTargetStep( evt.getNewValue().toString() );
339 propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, evt.getOldValue(), evt.getNewValue() );
340 }
341
342 public TestProperty getSourceProperty()
343 {
344 HttpRequestTestStep previousStep = ( HttpRequestTestStep )getTestCase().findPreviousStepOfType(
345 WsdlGotoTestStep.this, HttpRequestTestStep.class );
346 return previousStep == null ? null : previousStep.getProperty( "Response" );
347 }
348 }
349
350 public boolean hasProperties()
351 {
352 return false;
353 }
354
355 public PropertyExpansion[] getPropertyExpansions()
356 {
357 List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
358
359 for( GotoCondition condition : conditions )
360 {
361 result.addAll( PropertyExpansionUtils.extractPropertyExpansions( this, condition, "expression" ) );
362 }
363
364 return result.toArray( new PropertyExpansion[result.size()] );
365 }
366
367 public XPathReference[] getXPathReferences()
368 {
369 List<XPathReference> result = new ArrayList<XPathReference>();
370
371 for( GotoCondition condition : conditions )
372 {
373 if( StringUtils.hasContent( condition.getExpression() ) )
374 result.add( new XPathReferenceImpl( "Condition for " + condition.getName() + " GotoCondition in "
375 + getName(), condition.getSourceProperty(), condition, "expression" ) );
376 }
377
378 return result.toArray( new XPathReference[result.size()] );
379 }
380 }