View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.List;
17  
18  import com.eviware.soapui.SoapUI;
19  import com.eviware.soapui.SoapUIExtensionClassLoader;
20  import com.eviware.soapui.SoapUIExtensionClassLoader.SoapUIClassLoaderState;
21  import com.eviware.soapui.model.ModelItem;
22  import com.eviware.soapui.model.propertyexpansion.resolvers.ContextPropertyResolver;
23  import com.eviware.soapui.model.propertyexpansion.resolvers.DynamicPropertyResolver;
24  import com.eviware.soapui.model.propertyexpansion.resolvers.EvalPropertyResolver;
25  import com.eviware.soapui.model.propertyexpansion.resolvers.GlobalPropertyResolver;
26  import com.eviware.soapui.model.propertyexpansion.resolvers.MockRunPropertyResolver;
27  import com.eviware.soapui.model.propertyexpansion.resolvers.ModelItemPropertyResolver;
28  import com.eviware.soapui.model.propertyexpansion.resolvers.PropertyResolver;
29  import com.eviware.soapui.model.propertyexpansion.resolvers.SubmitPropertyResolver;
30  import com.eviware.soapui.model.propertyexpansion.resolvers.TestRunPropertyResolver;
31  import com.eviware.soapui.settings.GlobalPropertySettings;
32  import com.eviware.soapui.support.StringUtils;
33  import com.eviware.soapui.support.xml.XmlUtils;
34  
35  /***
36   * Class that can expand properties using property resolvers
37   * 
38   * @author ole
39   */
40  
41  public class PropertyExpander
42  {
43  	private List<PropertyResolver> propertyResolvers = new ArrayList<PropertyResolver>();
44  	private static List<PropertyResolver> defaultResolvers = new ArrayList<PropertyResolver>();
45  	private static PropertyExpander defaultExpander;
46  
47  	static
48  	{
49  		// add default resolvers - this should be read from some external config
50  		// in the future
51  		defaultResolvers.add( new ModelItemPropertyResolver() );
52  		defaultResolvers.add( new TestRunPropertyResolver() );
53  		defaultResolvers.add( new MockRunPropertyResolver() );
54  		defaultResolvers.add( new SubmitPropertyResolver() );
55  		defaultResolvers.add( new ContextPropertyResolver() );
56  		defaultResolvers.add( new DynamicPropertyResolver() );
57  		defaultResolvers.add( new GlobalPropertyResolver() );
58  		defaultResolvers.add( new EvalPropertyResolver() );
59  
60  		defaultExpander = new PropertyExpander( true );
61  	}
62  
63  	public PropertyExpander( boolean addDefaultResolvers )
64  	{
65  		if( addDefaultResolvers )
66  		{
67  			propertyResolvers.addAll( defaultResolvers );
68  		}
69  	}
70  
71  	public static PropertyExpander getDefaultExpander()
72  	{
73  		return defaultExpander;
74  	}
75  
76  	public static void addDefaultResolver( PropertyResolver resolver )
77  	{
78  		defaultResolvers.add( resolver );
79  		defaultExpander.addResolver( resolver );
80  	}
81  
82  	public void addResolver( PropertyResolver propertyResolver )
83  	{
84  		propertyResolvers.add( propertyResolver );
85  	}
86  
87  	public static String expandProperties( String content )
88  	{
89  		return defaultExpander.expand( content );
90  	}
91  
92  	public static String expandProperties( PropertyExpansionContext context, String content )
93  	{
94  		return defaultExpander.expand( context, content, false );
95  	}
96  
97  	public static String expandProperties( PropertyExpansionContext context, String content, boolean entitize )
98  	{
99  		return defaultExpander.expand( context, content, entitize );
100 	}
101 
102 	public String expand( String content )
103 	{
104 		return expand( new PropertyExpansionUtils.GlobalPropertyExpansionContext(), content, false );
105 	}
106 
107 	public String expand( PropertyExpansionContext context, String content )
108 	{
109 		return expand( context, content, false );
110 	}
111 
112 	public String expand( PropertyExpansionContext context, String content, boolean entitize )
113 	{
114 		SoapUIClassLoaderState clState = SoapUIExtensionClassLoader.ensure();
115 
116 		try
117 		{
118 
119 			if( StringUtils.isNullOrEmpty( content ) )
120 				return content;
121 
122 			int ix = content.indexOf( "${" );
123 			if( ix == -1 )
124 				return content;
125 
126 			StringBuffer buf = new StringBuffer();
127 			int lastIx = 0;
128 			while( ix != -1 )
129 			{
130 				if( ix > lastIx && content.charAt( ix - 1 ) == '$' )
131 				{
132 					buf.append( content.substring( lastIx, ix - 1 ) );
133 					lastIx = ix;
134 					ix = content.indexOf( "${", lastIx + 1 );
135 					continue;
136 				}
137 
138 				if( ix > lastIx )
139 					buf.append( content.substring( lastIx, ix ) );
140 
141 				int ix2 = content.indexOf( '}', ix + 2 );
142 				if( ix2 == -1 )
143 					break;
144 
145 				// check for nesting
146 				int ix3 = content.lastIndexOf( "${", ix2 );
147 				if( ix3 != ix )
148 				{
149 					// buf.append( content.substring( ix, ix3 ));
150 					content = content.substring( 0, ix3 ) + expand( context, content.substring( ix3, ix2 + 1 ) )
151 							+ content.substring( ix2 + 1 );
152 
153 					lastIx = ix;
154 					continue;
155 				}
156 
157 				String propertyName = content.substring( ix + 2, ix2 );
158 				String propertyValue = null;
159 
160 				if( StringUtils.hasContent( propertyName ) )
161 				{
162 					boolean globalOverrideEnabled = SoapUI.getSettings().getBoolean( GlobalPropertySettings.ENABLE_OVERRIDE );
163 
164 					for( int c = 0; c < propertyResolvers.size() && propertyValue == null; c++ )
165 					{
166 						propertyValue = propertyResolvers.get( c ).resolveProperty( context, propertyName,
167 								globalOverrideEnabled );
168 					}
169 				}
170 
171 				// found a value?
172 				if( propertyValue != null )
173 				{
174 					if( !content.equals( propertyValue ) )
175 						propertyValue = expand( context, propertyValue );
176 
177 					if( entitize )
178 						propertyValue = XmlUtils.entitize( propertyValue );
179 
180 					buf.append( propertyValue );
181 				}
182 				else
183 				{
184 					// if( log.isEnabledFor( Priority.WARN ))
185 					// log.warn( "Missing property value for [" + propertyName + "]"
186 					// );
187 
188 					// buf.append( "${" ).append( propertyName ).append( '}' );
189 				}
190 
191 				lastIx = ix2 + 1;
192 				ix = content.indexOf( "${", lastIx );
193 			}
194 
195 			if( lastIx < content.length() )
196 				buf.append( content.substring( lastIx ) );
197 
198 			return buf.toString();
199 		}
200 		finally
201 		{
202 			clState.restore();
203 		}
204 	}
205 
206 	public String expand( ModelItem contextModelItem, String content )
207 	{
208 		return expand( new DefaultPropertyExpansionContext( contextModelItem ), content );
209 	}
210 
211 	public static String expandProperties( ModelItem contextModelItem, String content )
212 	{
213 		return defaultExpander.expand( contextModelItem, content );
214 	}
215 
216 }