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.impl.rest.support;
14  
15  import java.io.UnsupportedEncodingException;
16  import java.net.MalformedURLException;
17  import java.net.URL;
18  import java.net.URLDecoder;
19  import java.net.URLEncoder;
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.regex.Matcher;
23  import java.util.regex.Pattern;
24  
25  import org.apache.xmlbeans.XmlBoolean;
26  
27  import com.eviware.soapui.SoapUI;
28  import com.eviware.soapui.impl.rest.RestRequestInterface;
29  import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder.ParameterStyle;
30  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
31  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
32  import com.eviware.soapui.support.StringUtils;
33  import com.eviware.soapui.support.Tools;
34  import com.eviware.soapui.support.types.StringList;
35  
36  public class RestUtils
37  {
38  	private final static Pattern splitPattern = Pattern.compile( "[^|]//|[^|]" );
39  
40  	public static String[] extractTemplateParams( String path )
41  	{
42  		if( StringUtils.isNullOrEmpty( path ) )
43  			return new String[0];
44  
45  		StringList result = new StringList();
46  
47  		int ix = path.indexOf( '{' );
48  		while( ix != -1 )
49  		{
50  			int endIx = path.indexOf( '}', ix );
51  			if( endIx == -1 )
52  				break;
53  
54  			if( endIx > ix + 1 && ( ix > 0 && path.charAt( ix - 1 ) != '$' ) )
55  				result.add( path.substring( ix + 1, endIx ) );
56  
57  			ix = path.indexOf( '{', ix + 1 );
58  		}
59  
60  		return result.toStringArray();
61  
62  	}
63  
64  	public static String extractParams( String pathOrEndpoint, RestParamsPropertyHolder params, boolean keepHost )
65  	{
66  		if( StringUtils.isNullOrEmpty( pathOrEndpoint ) )
67  			return "";
68  
69  		String path = pathOrEndpoint;
70  		String queryString = "";
71  		URL url = null;
72  
73  		try
74  		{
75  			url = new URL( pathOrEndpoint );
76  			path = url.getPath();
77  			queryString = url.getQuery();
78  		}
79  		catch( MalformedURLException e )
80  		{
81  			int ix = path.indexOf( '?' );
82  			if( ix >= 0 )
83  			{
84  				queryString = path.substring( ix + 1 );
85  				path = path.substring( 0, ix );
86  			}
87  		}
88  
89  		String[] items = path.split( "/" );
90  
91  		int templateParamCount = 0;
92  		StringBuffer resultPath = new StringBuffer();
93  
94  		for( int i = 0; i < items.length; i++ )
95  		{
96  			String item = items[i];
97  			try
98  			{
99  				if( item.startsWith( "{" ) && item.endsWith( "}" ) )
100 				{
101 					String name = item.substring( 1, item.length() - 1 );
102 					RestParamProperty property = params.getProperty( name );
103 					if( !params.hasProperty( name ) )
104 					{
105 						property = params.addProperty( name );
106 					}
107 
108 					property.setStyle( ParameterStyle.TEMPLATE );
109 					property.setValue( name );
110 					property.setDefaultValue( name );
111 				}
112 				else
113 				{
114 					String[] matrixParams = item.split( ";" );
115 					if( matrixParams.length > 0 )
116 					{
117 						item = matrixParams[0];
118 						for( int c = 1; c < matrixParams.length; c++ )
119 						{
120 							String matrixParam = matrixParams[c];
121 
122 							int ix = matrixParam.indexOf( '=' );
123 							if( ix == -1 )
124 							{
125 								String name = URLDecoder.decode( matrixParam, "Utf-8" );
126 								if( !params.hasProperty( name ) )
127 									params.addProperty( name ).setStyle( ParameterStyle.MATRIX );
128 							}
129 							else
130 							{
131 
132 								String name = URLDecoder.decode( matrixParam.substring( 0, ix ), "Utf-8" );
133 								RestParamProperty property = params.getProperty( name );
134 								if( property == null )
135 								{
136 									property = params.addProperty( name );
137 								}
138 
139 								property.setStyle( ParameterStyle.MATRIX );
140 								property.setValue( URLDecoder.decode( matrixParam.substring( ix + 1 ), "Utf-8" ) );
141 								property.setDefaultValue( URLDecoder.decode( matrixParam.substring( ix + 1 ), "Utf-8" ) );
142 							}
143 						}
144 					}
145 
146 					Integer.parseInt( item );
147 
148 					String name = "param" + templateParamCount++ ;
149 					RestParamProperty property = params.getProperty( name );
150 					if( !params.hasProperty( name ) )
151 					{
152 						property = params.addProperty( name );
153 					}
154 
155 					property.setStyle( ParameterStyle.TEMPLATE );
156 					property.setValue( item );
157 					property.setDefaultValue( item );
158 
159 					item = "{" + property.getName() + "}";
160 				}
161 			}
162 			catch( Exception e )
163 			{
164 			}
165 
166 			if( StringUtils.hasContent( item ) )
167 				resultPath.append( '/' ).append( item );
168 		}
169 
170 		if( StringUtils.hasContent( queryString ) )
171 		{
172 			extractParamsFromQueryString( params, queryString );
173 		}
174 
175 		if( path.endsWith( "/" ) )
176 			resultPath.append( '/' );
177 
178 		if( keepHost && url != null )
179 		{
180 			return Tools.getEndpointFromUrl( url ) + resultPath.toString();
181 		}
182 
183 		return resultPath.toString();
184 	}
185 
186 	public static void extractParamsFromQueryString( RestParamsPropertyHolder params, String queryString )
187 	{
188 		String[] items;
189 		items = queryString.split( "&" );
190 		for( String item : items )
191 		{
192 			try
193 			{
194 				int ix = item.indexOf( '=' );
195 				if( ix == -1 )
196 				{
197 					String name = URLDecoder.decode( item, "Utf-8" );
198 
199 					if( !params.hasProperty( name ) )
200 					{
201 						params.addProperty( name ).setStyle( ParameterStyle.QUERY );
202 					}
203 				}
204 				else
205 				{
206 					String name = URLDecoder.decode( item.substring( 0, ix ), "Utf-8" );
207 					RestParamProperty property = params.getProperty( name );
208 					if( property == null )
209 					{
210 						property = params.addProperty( name );
211 					}
212 
213 					property.setStyle( ParameterStyle.QUERY );
214 					property.setValue( URLDecoder.decode( item.substring( ix + 1 ), "Utf-8" ) );
215 					property.setDefaultValue( URLDecoder.decode( item.substring( ix + 1 ), "Utf-8" ) );
216 				}
217 			}
218 			catch( UnsupportedEncodingException e )
219 			{
220 				e.printStackTrace();
221 			}
222 		}
223 	}
224 
225 	@SuppressWarnings( "deprecation" )
226 	public static String expandPath( String path, RestParamsPropertyHolder params, RestRequestInterface request )
227 	{
228 		StringBuffer query = request.isPostQueryString() || "multipart/form-data".equals( request.getMediaType() ) ? null
229 				: new StringBuffer();
230 		DefaultPropertyExpansionContext context = new DefaultPropertyExpansionContext( request );
231 
232 		for( int c = 0; c < params.getPropertyCount(); c++ )
233 		{
234 			RestParamProperty param = params.getPropertyAt( c );
235 
236 			String value = PropertyExpander.expandProperties( context, param.getValue() );
237 			List<String> valueParts = splitMultipleParameters( value );
238 
239 			if( value != null && !param.isDisableUrlEncoding() )
240 			{
241 				try
242 				{
243 					String encoding = System.getProperty( "soapui.request.encoding", request.getEncoding() );
244 
245 					if( StringUtils.hasContent( encoding ) )
246 					{
247 						value = URLEncoder.encode( value, encoding );
248 						for( int i = 0; i < valueParts.size(); i++ )
249 							valueParts.set( i, URLEncoder.encode( valueParts.get( i ), encoding ) );
250 					}
251 					else
252 					{
253 						value = URLEncoder.encode( value );
254 						for( int i = 0; i < valueParts.size(); i++ )
255 							valueParts.set( i, URLEncoder.encode( valueParts.get( i ) ) );
256 					}
257 				}
258 				catch( UnsupportedEncodingException e1 )
259 				{
260 					SoapUI.logError( e1 );
261 					value = URLEncoder.encode( value );
262 					for( int i = 0; i < valueParts.size(); i++ )
263 						valueParts.set( i, URLEncoder.encode( valueParts.get( i ) ) );
264 				}
265 			}
266 
267 			if( !StringUtils.hasContent( value ) && !param.getRequired() )
268 				continue;
269 
270 			if( value == null )
271 				value = "";
272 
273 			switch( param.getStyle() )
274 			{
275 			case QUERY :
276 				if( query != null && valueParts != null )
277 				{
278 					for( String valuePart : valueParts )
279 					{
280 						if( query.length() > 0 )
281 							query.append( '&' );
282 
283 						query.append( URLEncoder.encode( param.getName() ) );
284 						query.append( '=' );
285 
286 						if( StringUtils.hasContent( valuePart ) )
287 							query.append( valuePart );
288 					}
289 				}
290 				break;
291 			case TEMPLATE :
292 				path = path.replaceAll( "//{" + param.getName() + "//}", value );
293 				break;
294 			case MATRIX :
295 				if( param.getType().equals( XmlBoolean.type.getName() ) )
296 				{
297 					if( value.toUpperCase().equals( "TRUE" ) || value.equals( "1" ) )
298 					{
299 						path += ";" + param.getName();
300 					}
301 				}
302 				else
303 				{
304 					path += ";" + param.getName();
305 					if( StringUtils.hasContent( value ) )
306 					{
307 						path += "=" + value;
308 					}
309 				}
310 			case PLAIN :
311 				break;
312 			}
313 		}
314 
315 		if( query != null && query.length() > 0 )
316 			path += "?" + query.toString();
317 
318 		return path;
319 	}
320 
321 	public static List<String> splitMultipleParameters( String paramStr )
322 	{
323 		if( paramStr == null )
324 			return null;
325 
326 		Matcher matcher = splitPattern.matcher( paramStr );
327 		List<String> parts = new ArrayList<String>();
328 		int i = 0;
329 		while( matcher.find() )
330 		{
331 			parts.add( paramStr.substring( i, matcher.start() + 1 ).replaceAll( "//|//|", "|" ) );
332 			i = matcher.start() + 2;
333 		}
334 		parts.add( paramStr.substring( i, paramStr.length() ).replaceAll( "//|//|", "|" ) );
335 
336 		return parts;
337 	}
338 }