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