View Javadoc

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