View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.util.ArrayList;
16  import java.util.HashMap;
17  import java.util.LinkedHashMap;
18  import java.util.List;
19  import java.util.Map;
20  
21  import org.apache.log4j.Logger;
22  import org.apache.xmlbeans.XmlException;
23  import org.apache.xmlbeans.XmlObject;
24  
25  import com.eviware.soapui.SoapUI;
26  import com.eviware.soapui.config.AttachmentConfig;
27  import com.eviware.soapui.config.CompressedStringConfig;
28  import com.eviware.soapui.config.CredentialsConfig;
29  import com.eviware.soapui.config.HttpRequestConfig;
30  import com.eviware.soapui.config.OldRestRequestConfig;
31  import com.eviware.soapui.config.RestParameterConfig;
32  import com.eviware.soapui.config.RestParametersConfig;
33  import com.eviware.soapui.config.RestRequestConfig;
34  import com.eviware.soapui.config.RestRequestStepConfig;
35  import com.eviware.soapui.config.RestResourceRepresentationConfig;
36  import com.eviware.soapui.config.SettingsConfig;
37  import com.eviware.soapui.config.StringToStringMapConfig;
38  import com.eviware.soapui.config.TestAssertionConfig;
39  import com.eviware.soapui.config.StringToStringMapConfig.Entry;
40  import com.eviware.soapui.impl.rest.RestMethod;
41  import com.eviware.soapui.impl.rest.RestRepresentation;
42  import com.eviware.soapui.impl.rest.RestRequest;
43  import com.eviware.soapui.impl.rest.RestResource;
44  import com.eviware.soapui.impl.rest.RestService;
45  import com.eviware.soapui.impl.rest.RestRequestInterface.RequestMethod;
46  import com.eviware.soapui.impl.wsdl.WsdlProject;
47  import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep;
48  import com.eviware.soapui.model.iface.Interface;
49  import com.eviware.soapui.model.project.Project;
50  import com.eviware.soapui.model.testsuite.TestProperty;
51  import com.eviware.soapui.support.StringUtils;
52  import com.eviware.soapui.support.UISupport;
53  
54  /***
55   * Convert old-style REST Requests to new ones, creating REST Methods for them
56   * or placing them into existing Methods.
57   * 
58   * @author Dain Nilsson
59   */
60  public class RestRequestConverter
61  {
62  
63  	private static Map<Project, Boolean> autoConvert = new HashMap<Project, Boolean>();
64  	private final static Logger log = Logger.getLogger( RestRequestConverter.class );
65  
66  	public static void convert( RestResource resource, OldRestRequestConfig oldConfig )
67  	{
68  		convert( resource, oldConfig, getMethod( resource, oldConfig.getMethod(), oldConfig.getName() ) );
69  	}
70  
71  	public static RestMethod getMethod( RestResource resource, String methodType, String requestName )
72  	{
73  		WsdlProject project = resource.getService().getProject();
74  		if( !autoConvert.containsKey( project ) )
75  		{
76  			autoConvert
77  					.put(
78  							project,
79  							UISupport
80  									.confirm(
81  											"The model for REST requests has changed slightly,\r\n"
82  													+ "introducing a new REST Method item in-between each REST Resource and Request.\r\n"
83  													+ "Any existing REST Request must now be placed under either an existing Method or a new one, "
84  													+ "either automatically or manually.\r\n\r\nWould You like soapUI to do this automatically using the default values?",
85  											"Update REST model for project: " + project.getName() ) );
86  		}
87  		RestMethod method = null;
88  		List<String> options = new ArrayList<String>();
89  		for( int c = 0; c < resource.getRestMethodCount(); c++ )
90  		{
91  			RestMethod restMethod = resource.getRestMethodAt( c );
92  			if( restMethod.getMethod().toString().equals( methodType ) )
93  				options.add( restMethod.getName() );
94  		}
95  		if( autoConvert.get( project ) )
96  		{
97  			if( options.size() > 0 )
98  			{
99  				method = resource.getRestMethodByName( options.get( 0 ) );
100 				log.info( "Placed request '" + requestName + "' under method '" + method.getName() + "' in Resource '"
101 						+ resource.getName() + "'." );
102 			}
103 			else
104 			{
105 				method = resource.addNewMethod( methodType + " Method" );
106 				method.setMethod( RequestMethod.valueOf( methodType ) );
107 				log.info( "Created new Method for Resource '" + resource.getName() + "'." );
108 			}
109 		}
110 		else
111 		{
112 			options.add( "[Create new REST Method]" );
113 			if( requestName == null )
114 				requestName = "REST Request";
115 			String message = "Select REST Method to place \"" + resource.getName() + " > " + requestName + "\" under.";
116 			Object op = UISupport.prompt( message, "Migrate REST Request", options.toArray() );
117 			if( op != null )
118 			{
119 				int ix = options.indexOf( op );
120 				if( ix != -1 && ix != options.size() - 1 )
121 				{
122 					method = resource.getRestMethodByName( ( String )op );
123 				}
124 			}
125 			else
126 				throw new RestConversionException( "Cannot get RestMethod selection!" );
127 			if( method == null )
128 			{
129 				String name = UISupport.prompt( "Name for REST " + methodType + " Method", "Create new REST Method",
130 						methodType + " Method" );
131 				if( name == null )
132 					throw new RestConversionException( "Cannot get name for RestMethod!" );
133 				method = resource.addNewMethod( name );
134 				method.setMethod( RequestMethod.valueOf( methodType ) );
135 			}
136 		}
137 		return method;
138 	}
139 
140 	public static RestResource resolveResource( RestTestRequestStep requestStep )
141 	{
142 		Map<String, RestResource> options = new LinkedHashMap<String, RestResource>();
143 
144 		WsdlProject project = requestStep.getTestCase().getTestSuite().getProject();
145 		String serviceName = requestStep.getRequestStepConfig().getService();
146 		RestService service = ( RestService )project.getInterfaceByName( serviceName );
147 		if( service != null )
148 		{
149 			addResources( service, options );
150 		}
151 		else
152 		{
153 			for( Interface iface : project.getInterfaceList() )
154 			{
155 				if( iface instanceof RestService )
156 				{
157 					addResources( ( RestService )iface, options );
158 				}
159 			}
160 		}
161 		options.put( "<Delete TestRequest>", null );
162 
163 		String message = "Select a new REST Resource to place TestRequest \"" + requestStep.getName() + "\" under.";
164 		Object op = UISupport.prompt( message, "Missing REST Resource for TestRequest", options.keySet().toArray() );
165 		RestResource resource = options.get( op );
166 
167 		return resource;
168 	}
169 
170 	private static void addResources( RestService service, Map<String, RestResource> list )
171 	{
172 		for( RestResource resource : service.getResources().values() )
173 		{
174 			list.put( service.getName() + " > " + resource.getName(), resource );
175 		}
176 	}
177 
178 	private static void convert( RestResource resource, OldRestRequestConfig oldConfig, RestMethod method )
179 	{
180 
181 		RestRequest request = method.addNewRequest( oldConfig.getName() );
182 
183 		XmlBeansRestParamsTestPropertyHolder params = new XmlBeansRestParamsTestPropertyHolder( null, oldConfig
184 				.getParameters() );
185 		RestParamsPropertyHolder parentParams = method.getOverlayParams();
186 
187 		for( TestProperty prop : params.values() )
188 		{
189 			if( !parentParams.containsKey( prop.getName() ) )
190 			{
191 				method.getParams().addParameter( ( RestParamProperty )prop );
192 			}
193 			request.setPropertyValue( prop.getName(), prop.getValue() );
194 		}
195 		params.release();
196 
197 		boolean exists;
198 		for( RestResourceRepresentationConfig rep : oldConfig.getRepresentationList() )
199 		{
200 			exists = false;
201 			for( RestRepresentation existing : method.getRepresentations( RestRepresentation.Type.valueOf( rep.getType()
202 					.toString() ), rep.getMediaType() ) )
203 			{
204 				if( existing.getElement() == null && rep.getElement() == null
205 						|| existing.getElement().equals( rep.getElement() ) )
206 				{
207 					exists = true;
208 					break;
209 				}
210 			}
211 			if( !exists )
212 			{
213 				RestRepresentation repr = method.addNewRepresentation( RestRepresentation.Type.valueOf( rep.getType()
214 						.toString() ) );
215 				repr.setConfig( ( RestResourceRepresentationConfig )rep.copy() );
216 			}
217 		}
218 
219 		RestRequestConfig newConfig = request.getConfig();
220 		if( oldConfig.isSetFullPath() )
221 			newConfig.setFullPath( oldConfig.getFullPath() );
222 		if( oldConfig.isSetMediaType() )
223 			newConfig.setMediaType( oldConfig.getMediaType() );
224 		if( oldConfig.isSetPostQueryString() )
225 			newConfig.setPostQueryString( oldConfig.getPostQueryString() );
226 		if( oldConfig.isSetAccept() )
227 			newConfig.setAccept( oldConfig.getAccept() );
228 		if( oldConfig.isSetDescription() )
229 			newConfig.setDescription( oldConfig.getDescription() );
230 		if( oldConfig.isSetId() )
231 			newConfig.setId( oldConfig.getId() );
232 		if( oldConfig.isSetSettings() )
233 			newConfig.setSettings( ( SettingsConfig )oldConfig.getSettings().copy() );
234 		if( oldConfig.isSetSslKeystore() )
235 			newConfig.setSslKeystore( oldConfig.getSslKeystore() );
236 		if( oldConfig.isSetTimestamp() )
237 			newConfig.setTimestamp( oldConfig.getTimestamp() );
238 		if( oldConfig.isSetWadlId() )
239 			newConfig.setWadlId( oldConfig.getWadlId() );
240 	}
241 
242 	public static HttpRequestConfig convert( OldRestRequestConfig old )
243 	{
244 		HttpRequestConfig config = HttpRequestConfig.Factory.newInstance();
245 		config.setAssertionArray( old.getAssertionList().toArray( new TestAssertionConfig[old.sizeOfAssertionArray()] ) );
246 		config.setAttachmentArray( old.getAttachmentList().toArray( new AttachmentConfig[old.sizeOfAttachmentArray()] ) );
247 		XmlObject obj = old.getCredentials();
248 		if( obj != null )
249 			config.setCredentials( ( CredentialsConfig )obj.copy() );
250 		obj = old.getParameters();
251 		if( obj != null )
252 			config.setParameters( ( RestParametersConfig )obj.copy() );
253 
254 		obj = old.getRequest();
255 		if( obj != null )
256 			config.setRequest( ( CompressedStringConfig )obj.copy() );
257 		obj = old.getSettings();
258 		if( obj != null )
259 			config.setSettings( ( SettingsConfig )obj.copy() );
260 		if( old.isSetDescription() )
261 			config.setDescription( old.getDescription() );
262 		config.setEncoding( old.getEncoding() );
263 		config.setEndpoint( old.getEndpoint() );
264 		config.setSslKeystore( old.getSslKeystore() );
265 		if( old.isSetMediaType() )
266 			config.setMediaType( old.getMediaType() );
267 		if( old.isSetMethod() )
268 			config.setMethod( old.getMethod() );
269 		if( old.isSetName() )
270 			config.setName( old.getName() );
271 		if( old.isSetPostQueryString() )
272 			config.setPostQueryString( old.getPostQueryString() );
273 		return config;
274 	}
275 
276 	public static HttpRequestConfig updateIfNeeded( XmlObject config )
277 	{
278 		if( config.schemaType().equals( HttpRequestConfig.type ) )
279 		{
280 			return ( HttpRequestConfig )config;
281 		}
282 		try
283 		{
284 			return convert( OldRestRequestConfig.Factory.parse( config.selectChildren( "http://eviware.com/soapui/config",
285 					"restRequest" )[0].toString() ) );
286 		}
287 		catch( XmlException e )
288 		{
289 			return HttpRequestConfig.Factory.newInstance();
290 		}
291 	}
292 
293 	public static class RestConversionException extends RuntimeException
294 	{
295 		public RestConversionException( String message )
296 		{
297 			super( message );
298 		}
299 	}
300 
301 	public static void updateRestTestRequest( RestTestRequestStep restTestRequestStep )
302 	{
303 		try
304 		{
305 			RestRequestStepConfig restRequestStepConfig = ( RestRequestStepConfig )restTestRequestStep.getConfig().getConfig();
306 			RestRequestConfig restRequestConfig = restRequestStepConfig.getRestRequest();
307 			OldRestRequestConfig oldConfig = OldRestRequestConfig.Factory.parse( restRequestConfig.toString() );
308 
309 			RestParametersConfig oldParams = oldConfig.getParameters();
310 			if( oldParams != null )
311 			{
312 				StringToStringMapConfig newParams = restRequestConfig.addNewParameters();
313 				
314 				for( RestParameterConfig oldParam : oldParams.getParameterList() )
315 				{
316 					if( StringUtils.hasContent( oldParam.getValue() ))
317 					{
318 						Entry entry = newParams.addNewEntry();
319 						entry.setKey( oldParam.getName());
320 						entry.setValue( oldParam.getValue() );
321 					}
322 				}
323 
324 				restRequestConfig.getParameters().getDomNode().getParentNode().removeChild( restRequestConfig.getParameters().getDomNode() );
325 			}
326 		}
327 		catch( XmlException e )
328 		{
329 			SoapUI.logError( e );
330 		}
331 	}
332 }