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.model.propertyexpansion;
14  
15  import java.util.ArrayList;
16  import java.util.Arrays;
17  import java.util.Collection;
18  import java.util.HashSet;
19  import java.util.List;
20  import java.util.Set;
21  
22  import org.apache.commons.beanutils.PropertyUtils;
23  import org.apache.log4j.Logger;
24  
25  import com.eviware.soapui.SoapUI;
26  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
27  import com.eviware.soapui.impl.wsdl.WsdlProject;
28  import com.eviware.soapui.impl.wsdl.WsdlRequest;
29  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
30  import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation;
31  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
32  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
33  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
34  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
35  import com.eviware.soapui.model.ModelItem;
36  import com.eviware.soapui.model.TestPropertyHolder;
37  import com.eviware.soapui.model.mock.MockOperation;
38  import com.eviware.soapui.model.mock.MockResponse;
39  import com.eviware.soapui.model.mock.MockService;
40  import com.eviware.soapui.model.project.Project;
41  import com.eviware.soapui.model.propertyexpansion.resolvers.ContextPropertyResolver;
42  import com.eviware.soapui.model.propertyexpansion.resolvers.DynamicPropertyResolver;
43  import com.eviware.soapui.model.propertyexpansion.resolvers.GlobalPropertyResolver;
44  import com.eviware.soapui.model.propertyexpansion.resolvers.MockRunPropertyResolver;
45  import com.eviware.soapui.model.propertyexpansion.resolvers.ModelItemPropertyResolver;
46  import com.eviware.soapui.model.propertyexpansion.resolvers.PropertyResolver;
47  import com.eviware.soapui.model.propertyexpansion.resolvers.SubmitPropertyResolver;
48  import com.eviware.soapui.model.propertyexpansion.resolvers.TestRunPropertyResolver;
49  import com.eviware.soapui.model.support.SettingsTestPropertyHolder;
50  import com.eviware.soapui.model.testsuite.TestCase;
51  import com.eviware.soapui.model.testsuite.TestProperty;
52  import com.eviware.soapui.model.testsuite.TestStep;
53  import com.eviware.soapui.model.testsuite.TestSuite;
54  import com.eviware.soapui.settings.GlobalPropertySettings;
55  import com.eviware.soapui.support.StringUtils;
56  import com.eviware.soapui.support.UISupport;
57  
58  public class PropertyExpansionUtils
59  {
60  	public final static Logger log = Logger.getLogger(PropertyExpansionUtils.class);
61  	
62  	private static SettingsTestPropertyHolder globalTestPropertyHolder;
63  	private static List<PropertyResolver> propertyResolvers = new ArrayList<PropertyResolver>();
64  	
65  	static
66  	{
67  		propertyResolvers.add( new ModelItemPropertyResolver() );
68  		propertyResolvers.add( new TestRunPropertyResolver() );
69  		propertyResolvers.add( new MockRunPropertyResolver() );
70  		propertyResolvers.add( new SubmitPropertyResolver() );
71  		propertyResolvers.add( new ContextPropertyResolver() );
72  		propertyResolvers.add( new DynamicPropertyResolver() );
73  		propertyResolvers.add( new GlobalPropertyResolver() );
74  	}
75  	
76  	public static String getGlobalProperty( String propertyName )
77  	{
78  		if( globalTestPropertyHolder == null )
79  		{
80  			initGlobalProperties();
81  		}
82  		
83  		return globalTestPropertyHolder.getPropertyValue( propertyName );
84  	}
85  
86  	private synchronized static void initGlobalProperties()
87  	{
88  		globalTestPropertyHolder = new SettingsTestPropertyHolder( SoapUI.getSettings(), null );
89  		
90  		String propFile = System.getProperty( "soapui.properties" );
91  		if( StringUtils.hasContent( propFile ))
92  			globalTestPropertyHolder.addPropertiesFromFile( propFile );
93  	}
94  
95  	public static void saveGlobalProperties()
96  	{
97  		if( globalTestPropertyHolder != null )
98  		{
99  			globalTestPropertyHolder.saveTo( SoapUI.getSettings() );
100 		}
101 	}
102 
103 	@SuppressWarnings("deprecation")
104 	public static String expandProperties(PropertyExpansionContext context, String content)
105 	{
106 		if( StringUtils.isNullOrEmpty( content ))
107 			return content;
108 		
109 		int ix = content.indexOf( "${" );
110 		if( ix == -1 )
111 			return content;
112 		
113 		StringBuffer buf = new StringBuffer();
114 		int lastIx = 0;
115 		while( ix != -1 )
116 		{
117 			if( ix > lastIx )
118 			   buf.append( content.substring( lastIx, ix ));
119 			
120 			int ix2 = content.indexOf( '}', ix+2 );
121 			if( ix2 == -1 )
122 				break;
123 	
124 			// check for nesting
125 			int ix3 = content.lastIndexOf( "${", ix2 );
126 			if( ix3 != ix )
127 			{
128 				//buf.append( content.substring( ix, ix3 ));
129 				content = content.substring( 0, ix3 ) + expandProperties( context, content.substring( ix3, ix2+1 )) + 
130 				          content.substring( ix2+1 );
131 				
132 				lastIx = ix;
133 				continue;
134 			}
135 			
136 			String propertyName = content.substring( ix+2, ix2 );
137 			String propertyValue = null;
138 			
139 			boolean globalOverrideEnabled = SoapUI.getSettings().getBoolean( GlobalPropertySettings.ENABLE_OVERRIDE );
140 			
141 			for( int c = 0; c < propertyResolvers.size() && propertyValue == null; c++  )
142 			{
143 				propertyValue = propertyResolvers.get( c ).resolveProperty( context, propertyName, globalOverrideEnabled );
144 			}
145 				
146 			// found a value?
147 			if( propertyValue != null )
148 			{
149 				if( !content.equals( propertyValue ))
150 					propertyValue = expandProperties( context, propertyValue );
151 				
152 				buf.append( propertyValue );
153 			}
154 			else
155 			{
156 //				if( log.isEnabledFor( Priority.WARN ))
157 //					log.warn( "Missing property value for [" + propertyName + "]" );
158 				
159 			   //buf.append( "${" ).append( propertyName ).append( '}' );
160 			}
161 			
162 			lastIx = ix2+1;
163 			ix = content.indexOf( "${", lastIx );
164 		}
165 		
166 		if( lastIx < content.length() )
167 			buf.append( content.substring( lastIx ));
168 		
169 		return buf.toString();
170 	}
171 
172 	/***
173 	 * Checks if a property can be transferred to another specified property via a property-transfer
174 	 */
175 	
176 	public static boolean canTransferToProperty( TestProperty source, TestProperty target )
177 	{
178 		return false;
179 	}
180 	
181 	/***
182 	 * Checks if a modelItem can acces a specified property via property-expansion
183 	 */
184 
185 	public static boolean canExpandProperty( ModelItem contextModelItem, TestProperty property )
186 	{
187 		ModelItem propertyModelItem = property.getModelItem();
188 		
189 		// global / anonymous reference?
190 		if( propertyModelItem == null || propertyModelItem instanceof Project )
191 			return true;
192 		
193 		if( contextModelItem instanceof TestSuite )
194 		{
195 			return propertyModelItem == contextModelItem;
196 		}
197 
198 		if( contextModelItem instanceof TestCase )
199 		{
200 			return propertyModelItem == contextModelItem || 
201 				(propertyModelItem instanceof TestSuite && ((TestCase)contextModelItem).getTestSuite() == propertyModelItem);
202 		}
203 
204 		if( contextModelItem instanceof TestStep )
205 		{
206 			TestStep testStep = ((TestStep)contextModelItem);
207 			
208 			return propertyModelItem == contextModelItem || 
209 			   (propertyModelItem instanceof TestSuite && testStep.getTestCase().getTestSuite() == propertyModelItem) ||
210 			   (propertyModelItem instanceof TestCase && testStep.getTestCase() == propertyModelItem) ||
211 			   (propertyModelItem instanceof TestStep && testStep.getTestCase() == ((TestStep)propertyModelItem).getTestCase());
212 		}
213 		
214 		if( contextModelItem instanceof MockService )
215 		{
216 			return propertyModelItem == contextModelItem;
217 		}
218 		
219 		if( contextModelItem instanceof MockOperation )
220 		{
221 			return propertyModelItem == contextModelItem || 
222 			(propertyModelItem instanceof MockService && ((MockOperation)contextModelItem).getMockService() == propertyModelItem);
223 		}
224 		
225 		if( contextModelItem instanceof MockResponse )
226 		{
227 			MockResponse testStep = ((MockResponse)contextModelItem);
228 			
229 			return propertyModelItem == contextModelItem || 
230 			   (propertyModelItem instanceof MockService && testStep.getMockOperation().getMockService() == propertyModelItem) ||
231 			   (propertyModelItem instanceof MockOperation && testStep.getMockOperation() == propertyModelItem) ||
232 			   (propertyModelItem instanceof MockResponse && testStep.getMockOperation() == ((MockResponse)propertyModelItem).getMockOperation());
233 		}
234 		
235 		System.out.println( "property " + property.getName() + " can not be transferred to " + contextModelItem.getName() );
236 		return false;
237 	}
238 
239 	public static MutableTestPropertyHolder getGlobalProperties()
240 	{
241 		if( globalTestPropertyHolder == null )
242 		{
243 			initGlobalProperties();
244 		}
245 		
246 		return globalTestPropertyHolder ;
247 	}
248 	
249 	public static MutablePropertyExpansion[] renameProperty( MutableTestPropertyHolder holder, TestProperty property, String newName, ModelItem root )
250 	{
251 		UISupport.setHourglassCursor();
252 		
253 		try
254 		{
255 			List<MutablePropertyExpansion> result = new ArrayList<MutablePropertyExpansion>();
256 			List<MutablePropertyExpansion> properties = new ArrayList<MutablePropertyExpansion>();
257 			
258 			PropertyExpansion[] propertyExpansions = getPropertyExpansions( root, true, true );
259 			for( PropertyExpansion pe : propertyExpansions )
260 			{
261 				MutablePropertyExpansion mpe = ( MutablePropertyExpansion ) pe;
262 				if( mpe.getProperty().equals( property ))
263 				{
264 					mpe.setProperty( property );
265 					properties.add( mpe );
266 				}
267 			}
268 			
269 			holder.renameProperty( property.getName(), newName );
270 			
271 			for( MutablePropertyExpansion mpe : properties )
272 			{
273 				try
274 				{
275 					mpe.update();
276 					result.add( mpe );
277 				}
278 				catch( Exception e )
279 				{
280 					e.printStackTrace();
281 				}
282 			}
283 						
284 			return result.toArray( new MutablePropertyExpansion[result.size()]);
285 		}
286 		finally
287 		{
288 			UISupport.resetCursor();
289 		}
290 	}
291 	
292 	public static PropertyExpansion [] getPropertyExpansions( ModelItem modelItem, boolean mutableOnly, boolean deep )
293 	{
294 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
295 		
296 		if( modelItem instanceof PropertyExpansionContainer )
297 		{
298 			PropertyExpansion[] pes = ((PropertyExpansionContainer)modelItem).getPropertyExpansions();
299 			if( pes != null && pes.length > 0 )
300 			{
301 		   	for( PropertyExpansion pe : pes )
302 		   	{
303 		   		if( mutableOnly && !(pe instanceof MutablePropertyExpansion))
304 		   			continue;
305 		   		
306 		   		result.add( pe );
307 		   	}
308 			}
309 		}
310 		
311 		if( deep )
312 		{
313 			List<? extends ModelItem> children = modelItem.getChildren();
314 			if( children != null && children.size() > 0 )
315 			{
316 				for( ModelItem child : children )
317 				{
318 					result.addAll( Arrays.asList( getPropertyExpansions( child, mutableOnly, deep ) ) );
319 				}
320 			}
321 		}
322 		
323 		return result.toArray( new PropertyExpansion[result.size()] );
324 	}
325 
326 	public static Collection<? extends PropertyExpansion> extractPropertyExpansions( ModelItem modelItem, Object target, String propertyName )
327 	{
328 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
329 		Set<String> expansions = new HashSet<String>();
330 		
331 		try
332 		{
333 			Object property = PropertyUtils.getProperty( target, propertyName );
334 			if( property instanceof String && PropertyUtils.isWriteable( target, propertyName ))
335 			{
336 				String str = property.toString();
337 				
338 				if( !StringUtils.isNullOrEmpty( str ))
339 				{
340 					int ix = str.indexOf( "${" );
341 					while( ix != -1 )
342 					{
343 						// TODO handle nested property-expansions..
344 						int ix2 = str.indexOf( '}', ix+2 );
345 						if( ix2 == -1 )
346 							break;
347 						
348 						String expansion = str.substring( ix+2, ix2  );
349 						if( !expansions.contains( expansion ))
350 						{
351 							MutablePropertyExpansion tp = createMutablePropertyExpansion( expansion, modelItem, target, propertyName );
352 							if( tp != null )
353 							{
354 								result.add( tp );
355 								expansions.add( expansion );
356 							}
357 						}
358 						
359 						str = str.substring( ix2 );
360 						ix = str.indexOf( "${" );
361 					}
362 				}
363 			}
364 		}
365 		catch( Exception e )
366 		{
367 			SoapUI.logError( e );
368 		}
369 		
370 		return result;
371 	}
372 	
373 	public static MutablePropertyExpansionImpl createMutablePropertyExpansion( String pe, ModelItem modelItem, Object target, String propertyName )
374 	{
375 		WsdlTestStep testStep = null;
376 		WsdlTestCase testCase = null;
377 		WsdlTestSuite testSuite = null;
378 		WsdlProject project = null;
379 		WsdlMockService mockService = null;
380 		WsdlMockResponse mockResponse = null;
381 		TestPropertyHolder holder = null;
382 		
383 		if( modelItem instanceof WsdlTestStep )
384 		{
385 			testStep = ( WsdlTestStep ) modelItem;
386 			testCase = testStep.getTestCase();
387 			testSuite = testCase.getTestSuite();
388 			project = testSuite.getProject();
389 		}
390 		else if( modelItem instanceof WsdlTestCase )
391 		{
392 			testCase = ( WsdlTestCase ) modelItem;
393 			testSuite = testCase.getTestSuite();
394 			project = testSuite.getProject();
395 		}
396 		else if( modelItem instanceof WsdlTestSuite )
397 		{
398 			testSuite = ( WsdlTestSuite ) modelItem;
399 			project = testSuite.getProject();
400 		}
401 		else if( modelItem instanceof WsdlProject )
402 		{
403 			project = ( WsdlProject ) modelItem;
404 		}
405 		else if( modelItem instanceof WsdlMockService )
406 		{
407 			mockService = ( WsdlMockService ) modelItem;
408 			project = mockService.getProject();
409 		}	
410 		else if( modelItem instanceof WsdlRequest )
411 		{
412 			project = ((WsdlRequest)modelItem).getOperation().getInterface().getProject();
413 		}
414 		else if( modelItem instanceof WsdlMockOperation )
415 		{
416 			mockService = (( WsdlMockOperation ) modelItem).getMockService();
417 			project = mockService.getProject();
418 		}	
419 		else if( modelItem instanceof WsdlMockResponse )
420 		{
421 			mockResponse = ( WsdlMockResponse ) modelItem;
422 			mockService = mockResponse.getMockOperation().getMockService();
423 			project = mockService.getProject();
424 		}
425 		
426 		// explicit item reference?
427 		if( pe.startsWith( PropertyExpansion.PROJECT_REFERENCE ))
428 		{
429 			holder = project;
430 			pe = pe.substring( PropertyExpansion.PROJECT_REFERENCE.length() );
431 		}
432 		else if( pe.startsWith( PropertyExpansion.TESTSUITE_REFERENCE ))
433 		{
434 			holder = testSuite;
435 			pe = pe.substring( PropertyExpansion.TESTSUITE_REFERENCE.length() );
436 		}
437 		else if( pe.startsWith( PropertyExpansion.TESTCASE_REFERENCE ))
438 		{
439 			holder = testCase;
440 			pe = pe.substring( PropertyExpansion.TESTCASE_REFERENCE.length() );
441 		}
442 		else if( pe.startsWith( PropertyExpansion.MOCKSERVICE_REFERENCE ))
443 		{
444 			holder = mockService;
445 			pe = pe.substring( PropertyExpansion.MOCKSERVICE_REFERENCE.length() );
446 		}
447 		else if( pe.startsWith( PropertyExpansion.MOCKRESPONSE_REFERENCE ))
448 		{
449 			holder = mockResponse;
450 			pe = pe.substring( PropertyExpansion.MOCKRESPONSE_REFERENCE.length() );
451 		}
452 		else if( testCase != null )
453 		{
454 			int sepIx = pe.indexOf( PropertyExpansion.PROPERTY_SEPARATOR );
455 			if( sepIx > 0 )
456 			{
457 				holder = testCase.getTestStepByName( pe.substring( 0, sepIx ) );
458 				if( holder != null )
459 				{
460 					pe = pe.substring( sepIx+1 );
461 				}
462 			}
463 		}
464 
465 		int sepIx = pe.indexOf( PropertyExpansion.XPATH_SEPARATOR );
466 		String xpath = null;
467 
468 		if( sepIx > 0 )
469 		{
470 			xpath = pe.substring( sepIx+1 );
471 			pe = pe.substring( 0, sepIx );
472 		}
473 		
474 		if( holder == null )
475 			holder = getGlobalProperties();
476 		
477 		TestProperty tp = holder.getProperty( pe );
478 		return tp == null ? null : new MutablePropertyExpansionImpl( tp, xpath, target, propertyName );
479 	}
480 
481 	public static String expandProperties( ModelItem modelItem, String content )
482 	{
483 		return expandProperties( new DefaultPropertyExpansionContext( modelItem ), content );
484 	}
485 }