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