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