View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.impl.wsdl.submit.filters;
14  
15  import java.io.File;
16  import java.io.FileInputStream;
17  import java.util.Properties;
18  
19  import org.apache.log4j.Logger;
20  import org.apache.log4j.Priority;
21  import org.apache.xmlbeans.XmlObject;
22  
23  import com.eviware.soapui.SoapUI;
24  import com.eviware.soapui.impl.wsdl.WsdlRequest;
25  import com.eviware.soapui.impl.wsdl.submit.RequestFilter;
26  import com.eviware.soapui.impl.wsdl.submit.transports.http.BaseHttpRequestTransport;
27  import com.eviware.soapui.model.iface.SubmitContext;
28  import com.eviware.soapui.model.testsuite.TestRunContext;
29  import com.eviware.soapui.support.StringUtils;
30  import com.eviware.soapui.support.xml.XmlUtils;
31  
32  /***
33   * RequestFilter that expands properties in request content
34   * 
35   * @author Ole.Matzura
36   */
37  
38  public class PropertyExpansionRequestFilter implements RequestFilter
39  {
40  	private static final char PROPERTY_SEPARATOR = '#';
41  	private final static Logger log = Logger.getLogger(PropertyExpansionRequestFilter.class);
42  	private static Properties globalProperties;
43  	
44  	public void filterRequest(SubmitContext context, WsdlRequest wsdlRequest)
45  	{
46  		String content = (String) context.getProperty( BaseHttpRequestTransport.REQUEST_CONTENT );
47  		if( content == null )
48  		{
49  			log.warn( "Missing request content in context, skipping property expansion" );
50  		}
51  		else
52  		{
53  			content = expandProperties(context, content);
54  			if( content != null )
55  				context.setProperty( BaseHttpRequestTransport.REQUEST_CONTENT, content );
56  		}
57  	}
58  
59  	@SuppressWarnings("deprecation")
60  	public static String expandProperties(SubmitContext context, String content)
61  	{
62  		if( StringUtils.isNullOrEmpty( content ))
63  			return content;
64  		
65  		int ix = content.indexOf( "${" );
66  		if( ix == -1 )
67  			return content;
68  		
69  		StringBuffer buf = new StringBuffer();
70  		int lastIx = 0;
71  		while( ix != -1 )
72  		{
73  			if( ix > lastIx )
74  			   buf.append( content.substring( lastIx, ix ));
75  			
76  			int ix2 = content.indexOf( '}', ix+2 );
77  			if( ix2 == -1 )
78  				break;
79  
80  			// check for nesting
81  			int ix3 = content.lastIndexOf( "${", ix2 );
82  			if( ix3 != ix )
83  			{
84  				//buf.append( content.substring( ix, ix3 ));
85  				content = content.substring( 0, ix3 ) + expandProperties( context, content.substring( ix3, ix2+1 )) + 
86  				          content.substring( ix2+1 );
87  				
88  				lastIx = ix;
89  				continue;
90  			}
91  			
92  			String propertyName = content.substring( ix+2, ix2 );
93  			
94  			// check for system-property reference
95  			Object property = propertyName.length() > 2 && propertyName.charAt( 0 ) == '#' && propertyName.charAt( 1 ) == '#' ? 
96  						getSystemProperty( propertyName.substring( 2 ) ) : context.getProperty( propertyName );
97  			
98  			if( property != null )
99  			{
100 				String value = property.toString();
101 				if( !content.equals( value ))
102 					value = expandProperties( context, value );
103 				
104 				buf.append( value );
105 			}
106 			else if( context instanceof TestRunContext )
107 			{
108 				int sepIx = propertyName.indexOf( PROPERTY_SEPARATOR );
109 				if( sepIx >= 0 )
110 				{
111 					String step = propertyName.substring( 0, sepIx );
112 					String name = propertyName.substring( sepIx+1 );
113 					
114 					sepIx = name.indexOf( PROPERTY_SEPARATOR );
115 					if( sepIx != -1 )
116 					{
117 						String xpath = name.substring( sepIx+1 );
118 						name = name.substring( 0, sepIx );
119 						
120 						if( step.length() == 0 )
121 							property = ((TestRunContext)context).getProperty( name);
122 						else
123 							property = ((TestRunContext)context).getProperty( step, name);
124 						
125 						if( property != null )
126 						{
127 							property = extractXPathPropertyValue( property, xpath );
128 						}
129 					}
130 					else
131 					{
132 						if( step.length() == 0 )
133 							property = ((TestRunContext)context).getProperty( name);
134 						else
135 							property = ((TestRunContext)context).getProperty( step, name);
136 					}
137 					
138 					if( property != null )
139 					{
140 						String value = property.toString();
141 						if( !content.equals( value ))
142 							value = expandProperties( context, value );
143 						
144 						buf.append( value );
145 					}
146 				}
147 			}
148 			else if( propertyName.charAt( 0 ) == PROPERTY_SEPARATOR  )
149 			{
150 				int sepIx = propertyName.indexOf( PROPERTY_SEPARATOR, 1 );
151 				if( sepIx > 0 )
152 				{
153 					String xpath = propertyName.substring( sepIx+1 );
154 					propertyName = propertyName.substring( 1, sepIx );
155 					
156 					property = context.getProperty( propertyName );
157 					if( property != null )
158 					{
159 						property = extractXPathPropertyValue( property, expandProperties( context, xpath ));
160 					}
161 				}
162 				else
163 				{
164 					property = context.getProperty( propertyName.substring( 1 ) );
165 				}
166 				
167 				if( property != null )
168 				{
169 					String value = property.toString();
170 					if( !content.equals( value ))
171 						value = expandProperties( context, value );
172 					
173 					buf.append( value );
174 				}
175 			}
176 				
177 			if( property == null )
178 			{
179 				if( log.isEnabledFor( Priority.WARN ))
180 					log.warn( "Missing property value for [" + propertyName + "]" );
181 				
182 			   buf.append( "${" ).append( propertyName ).append( '}' );
183 			}
184 			
185 			lastIx = ix2+1;
186 			ix = content.indexOf( "${", lastIx );
187 		}
188 		
189 		if( lastIx < content.length() )
190 			buf.append( content.substring( lastIx ));
191 		
192 		return buf.toString();
193 	}
194 
195 	private static String getSystemProperty( String propertyName )
196 	{
197 		if( globalProperties == null )
198 		{
199 			globalProperties = new Properties();
200 		   String propFile = System.getProperty( "soapui.properties" );
201 		   File file = new File( propFile );
202 			if( file.exists() )
203 		   {
204 				try
205 				{
206 					globalProperties.load( new FileInputStream( file ) );
207 					log.info( "Loaded " + globalProperties.size() + " properties from [" + file.getAbsolutePath() + "]" );
208 				}
209 				catch( Exception e )
210 				{
211 					e.printStackTrace();
212 				}
213 		   }
214 		}
215 		
216 		return globalProperties.isEmpty() ? System.getProperty( propertyName ) :
217 			globalProperties.getProperty( propertyName, System.getProperty( propertyName ));
218 	}
219 
220 	public static String extractXPathPropertyValue( Object property, String xpath )
221 	{
222 		try
223 		{
224 			XmlObject xmlObject = XmlObject.Factory.parse(  property.toString() );
225 			String ns = XmlUtils.declareXPathNamespaces( xmlObject );
226 			XmlObject[] paths = xmlObject.selectPath( ns + xpath );
227 			if( paths.length > 0 )
228 				return XmlUtils.getNodeValue( paths[0].getDomNode() );
229 		}
230 		catch( Exception e )
231 		{
232 			SoapUI.logError( e );
233 		}
234 		
235 		return null;
236 	}
237 }