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