View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
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.wsdl.submit.filters.PropertyExpansionRequestFilter;
30  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
31  import com.eviware.soapui.model.iface.SubmitContext;
32  import com.eviware.soapui.model.testsuite.TestRunContext;
33  import com.eviware.soapui.model.testsuite.TestRunner;
34  import com.eviware.soapui.model.testsuite.TestStep;
35  import com.eviware.soapui.model.testsuite.TestStepResult;
36  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
37  import com.eviware.soapui.support.UISupport;
38  
39  /***
40   * TestStep that moves execution to another step based on the contents of a XML Property
41   * 
42   * @author ole.matzura
43   */
44  
45  public class WsdlGotoTestStep extends WsdlTestStep
46  {
47  	private GotoStepConfig gotoStepConfig;
48  	private List<GotoCondition> conditions = new ArrayList<GotoCondition>();
49  	private boolean canceled;
50  	
51  	private final static Logger log = Logger.getLogger( WsdlGotoTestStep.class );
52  	
53  	public WsdlGotoTestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest)
54  	{
55  		super(testCase, config, true, forLoadTest);
56  		
57  		if( !forLoadTest )
58  		{
59  			setIcon( UISupport.createImageIcon("/goto.gif"));
60  		}
61  	}
62  
63  	public void postInit( TestStepConfig config )
64  	{
65  		if( config.getConfig() == null )
66  		{
67  			gotoStepConfig = (GotoStepConfig) config.addNewConfig().changeType( GotoStepConfig.type );
68  		}
69  		else
70  		{
71  			gotoStepConfig = (GotoStepConfig) config.getConfig().changeType(GotoStepConfig.type);
72  			for( int c = 0; c < gotoStepConfig.sizeOfConditionArray(); c++ )
73  			{
74  				conditions.add( new GotoCondition( gotoStepConfig.getConditionArray( c )));
75  			}	
76  		}
77  	}
78  
79  	public void resetConfigOnMove(TestStepConfig config)
80  	{
81  		super.resetConfigOnMove( config );
82  		
83  		gotoStepConfig = (GotoStepConfig) config.getConfig().changeType(GotoStepConfig.type);
84  		for( int c = 0; c < gotoStepConfig.sizeOfConditionArray(); c++ )
85  		{
86  			conditions.get( c ).setConfig( gotoStepConfig.getConditionArray( c ));
87  		}	
88  	}
89  
90  	public TestStepResult run(TestRunner runner, TestRunContext context)
91  	{
92  		WsdlTestStepResult result = new WsdlTestStepResult( this );
93  		canceled = false;
94  		
95  		result.startTimer();
96  		
97  		WsdlTestRequestStep previousStep = (WsdlTestRequestStep) getTestCase().findPreviousStepOfType( 
98  				this, WsdlTestRequestStep.class );
99  		
100 		if( previousStep == null )
101 		{
102 			result.stopTimer();
103 			result.addMessage( "Failed to find previous request step from [" + getName() + "]" );
104 			result.setStatus( TestStepStatus.FAILED );
105 			return result;
106 		}
107 		
108 		GotoCondition target = runConditions( previousStep, context );
109 		if( target == null )
110 		{
111 			result.addMessage( "Missing matching condition, moving on." );
112 		}
113 		else
114 		{
115 			String targetStepName = target.getTargetStep();
116 			result.addMessage( "Matched condition [" + targetStepName + "], transferring to [" + targetStepName + "]" );
117 			runner.gotoStep( runner.getTestCase().getTestStepIndexByName( targetStepName ) );
118 		}
119 		
120 		result.stopTimer();
121 		result.setStatus( TestStepStatus.OK );
122 		return result;
123 	}
124 
125 	public GotoCondition runConditions(WsdlTestRequestStep previousStep, SubmitContext context)
126 	{
127 		for( GotoCondition condition : conditions )
128 		{
129 			if( canceled )
130 				break;
131 			
132 			try
133 			{
134 				if( condition.evaluate( previousStep, context ))
135 				{
136 					return condition;
137 				}
138 			}
139 			catch (Exception e)
140 			{
141 				log.error( "Error making condition " + condition.getName() + "; " + e );
142 			}
143 		}
144 		
145 		return null;
146 	}
147 
148 	public boolean cancel()
149 	{
150 		canceled = true;
151 		return canceled;
152 	}
153 	
154 	public int getConditionCount()
155 	{
156 		return conditions.size();
157 	}
158 	
159 	public GotoCondition getConditionAt( int index )
160 	{
161 		return conditions.get( index );
162 	}
163 	
164 	public GotoCondition addCondition( String name )
165 	{
166 		GotoCondition condition = new GotoCondition( gotoStepConfig.addNewCondition());
167 		condition.setName( name );
168 		condition.setType( GotoConditionTypeConfig.XPATH.toString() );
169 		conditions.add( condition );
170 		return condition;
171 	}
172 	
173 	public void removeConditionAt( int index )
174 	{
175 		conditions.remove( index );
176 		gotoStepConfig.removeCondition( index );
177 	}
178 	
179 	public void release()
180 	{
181 		super.release(); 
182 		
183 		for( GotoCondition condition : conditions )
184 		{
185 			condition.release();
186 		}
187 	}
188 
189 	public class GotoCondition implements PropertyChangeListener
190 	{
191 		public final static String TARGET_STEP_PROPERTY = "target_step";
192 		
193 		private GotoConditionConfig conditionConfig;
194 		private TestStep currentStep;
195 		private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( this );
196 
197 		public GotoCondition(GotoConditionConfig conditionConfig)
198 		{
199 			this.conditionConfig = conditionConfig;
200 			initListeners();
201 		}
202 		
203 		public void addPropertyChangeListener( String propertyName, PropertyChangeListener listener )
204 		{
205 			propertyChangeSupport.addPropertyChangeListener( propertyName, listener );
206 		}
207 
208 		public void addPropertyChangeListener( PropertyChangeListener listener )
209 		{
210 			propertyChangeSupport.addPropertyChangeListener( listener );
211 		}
212 		
213 		public void removePropertyChangeListener( String propertyName, PropertyChangeListener listener )
214 		{
215 			propertyChangeSupport.removePropertyChangeListener( propertyName, listener );
216 		}
217 
218 		public void removePropertyChangeListener( PropertyChangeListener listener )
219 		{
220 			propertyChangeSupport.removePropertyChangeListener( listener );
221 		}
222 		
223 		private void initListeners()
224 		{
225 			release();
226 			
227 			if( getTargetStep() != null )
228 			{
229 				int index = getTestCase().getTestStepIndexByName( getTargetStep() );
230 				if( index != -1 )
231 				{
232 					currentStep = getTestCase().getTestStepAt( index );
233 					currentStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, this );
234 				}
235 			}
236 		}
237 		
238 		public void release()
239 		{
240 			if( currentStep != null )
241 				currentStep.removePropertyChangeListener( this );
242 		}
243 	
244 		public boolean evaluate(WsdlTestRequestStep previousStep, SubmitContext context) throws Exception
245 		{
246 			if( getExpression() == null || getExpression().trim().length() == 0 )
247 				throw new Exception( "Missing expression in condition [" + getName() + "]" );
248 			
249 			if( getTargetStep() == null || getTargetStep().trim().length() == 0 )
250 				throw new Exception( "Missing target step in condition [" + getName() + "]" );
251 			
252 			if( getType().equals( GotoConditionTypeConfig.XPATH.toString() ))
253 			{
254 				XmlObject xmlObject = XmlObject.Factory.parse( previousStep.getTestRequest().getResponse().getContentAsString());
255 				
256 				String expression = PropertyExpansionRequestFilter.expandProperties( context, getExpression() );
257 				XmlObject[] selectPath = xmlObject.selectPath( expression );
258 				if( selectPath.length == 1 && selectPath[0] instanceof XmlBoolean )
259 				{
260 					if( ((XmlBoolean)selectPath[0]).getBooleanValue() )
261 					{
262 						return true;
263 					}
264 				}
265 			}
266 			else
267 			{
268 				log.error( "Unkown condition type: " + getType() );
269 			}
270 			
271 			return false;
272 		}
273 
274 		protected void setConfig(GotoConditionConfig conditionConfig)
275 		{
276 			this.conditionConfig = conditionConfig;
277 		}
278 
279 		public String getType()
280 		{
281 			return conditionConfig.getType();
282 		}
283 		
284 		public String getName()
285 		{
286 			return conditionConfig.getName();
287 		}
288 
289 		public String getExpression()
290 		{
291 			return conditionConfig.getExpression();
292 		}
293 		
294 		public String getTargetStep()
295 		{
296 			return conditionConfig.getTargetStep();
297 		}
298 		
299 		public void setType( String type )
300 		{
301 			conditionConfig.setType( type );
302 		}
303 
304 		public void setName( String name )
305 		{
306 			conditionConfig.setName( name );
307 		}
308 		
309 		public void setExpression( String expression )
310 		{
311 			conditionConfig.setExpression( expression );
312 		}
313 		
314 		public void setTargetStep( String targetStep )
315 		{
316 			String oldStep = getTargetStep();
317 			conditionConfig.setTargetStep( targetStep );
318 			initListeners();
319 			propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, oldStep, targetStep );
320 		}
321 
322 		public void propertyChange(PropertyChangeEvent evt)
323 		{
324 			conditionConfig.setTargetStep( evt.getNewValue().toString() );
325 			propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, evt.getOldValue(), evt.getNewValue() );
326 		}
327 	}
328 }