/*
* Copyright 2004-2014 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.rest.support;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.AttachmentConfig;
import com.eviware.soapui.config.CompressedStringConfig;
import com.eviware.soapui.config.CredentialsConfig;
import com.eviware.soapui.config.HttpRequestConfig;
import com.eviware.soapui.config.OldRestRequestConfig;
import com.eviware.soapui.config.RestParameterConfig;
import com.eviware.soapui.config.RestParametersConfig;
import com.eviware.soapui.config.RestRequestConfig;
import com.eviware.soapui.config.RestRequestStepConfig;
import com.eviware.soapui.config.RestResourceRepresentationConfig;
import com.eviware.soapui.config.SettingsConfig;
import com.eviware.soapui.config.StringToStringMapConfig;
import com.eviware.soapui.config.StringToStringMapConfig.Entry;
import com.eviware.soapui.config.TestAssertionConfig;
import com.eviware.soapui.impl.rest.RestMethod;
import com.eviware.soapui.impl.rest.RestRepresentation;
import com.eviware.soapui.impl.rest.RestRequest;
import com.eviware.soapui.impl.rest.RestRequestInterface;
import com.eviware.soapui.impl.rest.RestResource;
import com.eviware.soapui.impl.rest.RestService;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep;
import com.eviware.soapui.model.iface.Interface;
import com.eviware.soapui.model.project.Project;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Convert old-style REST Requests to new ones, creating REST Methods for them
* or placing them into existing Methods.
*
* @author Dain Nilsson
*/
public class RestRequestConverter {
private static Map<Project, Boolean> autoConvert = new HashMap<Project, Boolean>();
private final static Logger log = Logger.getLogger(RestRequestConverter.class);
public static void convert(RestResource resource, OldRestRequestConfig oldConfig) {
convert(resource, oldConfig, getMethod(resource, oldConfig.getMethod(), oldConfig.getName()));
}
public static RestMethod getMethod(RestResource resource, String methodType, String requestName) {
WsdlProject project = resource.getService().getProject();
if (!autoConvert.containsKey(project)) {
autoConvert
.put(project,
UISupport
.confirm(
"The model for REST requests has changed slightly,\r\n"
+ "introducing a new REST Method item in-between each REST Resource and Request.\r\n"
+ "Any existing REST Request must now be placed under either an existing Method or a new one, "
+ "either automatically or manually.\r\n\r\nWould You like SoapUI to do this automatically using the default values?",
"Update REST model for project: " + project.getName()));
}
RestMethod method = null;
List<String> options = new ArrayList<String>();
for (int c = 0; c < resource.getRestMethodCount(); c++) {
RestMethod restMethod = resource.getRestMethodAt(c);
if (restMethod.getMethod().toString().equals(methodType)) {
options.add(restMethod.getName());
}
}
if (autoConvert.get(project)) {
if (options.size() > 0) {
method = resource.getRestMethodByName(options.get(0));
log.info("Placed request '" + requestName + "' under method '" + method.getName() + "' in Resource '"
+ resource.getName() + "'.");
} else {
method = resource.addNewMethod(methodType + " Method");
method.setMethod(RestRequestInterface.HttpMethod.valueOf(methodType));
log.info("Created new Method for Resource '" + resource.getName() + "'.");
}
} else {
options.add("[Create new REST Method]");
if (requestName == null) {
requestName = "REST Request";
}
String message = "Select REST Method to place \"" + resource.getName() + " > " + requestName + "\" under.";
Object op = UISupport.prompt(message, "Migrate REST Request", options.toArray());
if (op != null) {
int ix = options.indexOf(op);
if (ix != -1 && ix != options.size() - 1) {
method = resource.getRestMethodByName((String) op);
}
} else {
throw new RestConversionException("Cannot get RestMethod selection!");
}
if (method == null) {
String name = UISupport.prompt("Name for REST " + methodType + " Method", "Create new REST Method",
methodType + " Method");
if (name == null) {
throw new RestConversionException("Cannot get name for RestMethod!");
}
method = resource.addNewMethod(name);
method.setMethod(RestRequestInterface.HttpMethod.valueOf(methodType));
}
}
return method;
}
public static RestResource resolveResource(RestTestRequestStep requestStep) {
Map<String, RestResource> options = new LinkedHashMap<String, RestResource>();
WsdlProject project = requestStep.getTestCase().getTestSuite().getProject();
String serviceName = requestStep.getRequestStepConfig().getService();
RestService service = (RestService) project.getInterfaceByName(serviceName);
if (service != null) {
addResources(service, options);
} else {
for (Interface iface : project.getInterfaceList()) {
if (iface instanceof RestService) {
addResources((RestService) iface, options);
}
}
}
options.put("<Delete TestRequest>", null);
String message = "Select a new REST Resource to place TestRequest \"" + requestStep.getName() + "\" under.";
Object op = UISupport.prompt(message, "Missing REST Resource for TestRequest", options.keySet().toArray());
RestResource resource = options.get(op);
return resource;
}
private static void addResources(RestService service, Map<String, RestResource> list) {
for (RestResource resource : service.getResources().values()) {
list.put(service.getName() + " > " + resource.getName(), resource);
}
}
@SuppressWarnings("deprecation")
private static void convert(RestResource resource, OldRestRequestConfig oldConfig, RestMethod method) {
RestRequest request = method.addNewRequest(oldConfig.getName());
XmlBeansRestParamsTestPropertyHolder params = new XmlBeansRestParamsTestPropertyHolder(null,
oldConfig.getParameters());
RestParamsPropertyHolder parentParams = method.getOverlayParams();
for (TestProperty prop : params.values()) {
if (!parentParams.containsKey(prop.getName())) {
method.getParams().addParameter((RestParamProperty) prop);
}
request.setPropertyValue(prop.getName(), prop.getValue());
}
params.release();
boolean exists;
for (RestResourceRepresentationConfig rep : oldConfig.getRepresentationList()) {
exists = false;
for (RestRepresentation existing : method.getRepresentations(
RestRepresentation.Type.valueOf(rep.getType().toString()), rep.getMediaType())) {
if (existing.getElement() == null && rep.getElement() == null
|| existing.getElement().equals(rep.getElement())) {
exists = true;
break;
}
}
if (!exists) {
RestRepresentation repr = method.addNewRepresentation(RestRepresentation.Type.valueOf(rep.getType()
.toString()));
repr.setConfig((RestResourceRepresentationConfig) rep.copy());
}
}
RestRequestConfig newConfig = request.getConfig();
newConfig.setRequest(oldConfig.getRequest());
for (AttachmentConfig ac : oldConfig.getAttachmentList()) {
try {
if (ac.isSetData()) {
File temp = File.createTempFile("pattern", ".suffix");
temp.deleteOnExit();
FileOutputStream out = new FileOutputStream(temp);
out.write(ac.getData());
request.attachFile(temp, true);
} else {
request.attachFile(new File(ac.getUrl()), false);
}
} catch (IOException e) {
e.printStackTrace();
}
}
newConfig.setAttachmentArray(oldConfig.getAttachmentArray());
if (oldConfig.isSetFullPath()) {
newConfig.setFullPath(oldConfig.getFullPath());
}
if (oldConfig.isSetMediaType()) {
newConfig.setMediaType(oldConfig.getMediaType());
}
if (oldConfig.isSetPostQueryString()) {
newConfig.setPostQueryString(oldConfig.getPostQueryString());
}
if (oldConfig.isSetAccept()) {
newConfig.setAccept(oldConfig.getAccept());
}
if (oldConfig.isSetDescription()) {
newConfig.setDescription(oldConfig.getDescription());
}
if (oldConfig.isSetId()) {
newConfig.setId(oldConfig.getId());
}
if (oldConfig.isSetSettings()) {
newConfig.setSettings((SettingsConfig) oldConfig.getSettings().copy());
}
if (oldConfig.isSetSslKeystore()) {
newConfig.setSslKeystore(oldConfig.getSslKeystore());
}
if (oldConfig.isSetTimestamp()) {
newConfig.setTimestamp(oldConfig.getTimestamp());
}
if (oldConfig.isSetWadlId()) {
newConfig.setWadlId(oldConfig.getWadlId());
}
request.updateConfig(newConfig);
}
public static HttpRequestConfig convert(OldRestRequestConfig old) {
HttpRequestConfig config = HttpRequestConfig.Factory.newInstance();
config.setAssertionArray(old.getAssertionList().toArray(new TestAssertionConfig[old.sizeOfAssertionArray()]));
config.setAttachmentArray(old.getAttachmentList().toArray(new AttachmentConfig[old.sizeOfAttachmentArray()]));
XmlObject obj = old.getCredentials();
if (obj != null) {
config.setCredentials((CredentialsConfig) obj.copy());
}
obj = old.getParameters();
if (obj != null) {
config.setParameters((RestParametersConfig) obj.copy());
}
obj = old.getRequest();
if (obj != null) {
config.setRequest((CompressedStringConfig) obj.copy());
}
obj = old.getSettings();
if (obj != null) {
config.setSettings((SettingsConfig) obj.copy());
}
if (old.isSetDescription()) {
config.setDescription(old.getDescription());
}
config.setEncoding(old.getEncoding());
config.setEndpoint(old.getEndpoint());
config.setSslKeystore(old.getSslKeystore());
if (old.isSetMediaType()) {
config.setMediaType(old.getMediaType());
}
if (old.isSetMethod()) {
config.setMethod(old.getMethod());
}
if (old.isSetName()) {
config.setName(old.getName());
}
if (old.isSetPostQueryString()) {
config.setPostQueryString(old.getPostQueryString());
}
return config;
}
public static HttpRequestConfig updateIfNeeded(XmlObject config) {
try {
if (config instanceof RestRequestStepConfig) {
return convert(OldRestRequestConfig.Factory.parse(config.selectChildren(
"http://eviware.com/soapui/config", "restRequest")[0].toString()));
} else {
return (HttpRequestConfig) config.changeType(HttpRequestConfig.type);
}
} catch (XmlException e) {
return HttpRequestConfig.Factory.newInstance();
}
}
public static class RestConversionException extends RuntimeException {
public RestConversionException(String message) {
super(message);
}
}
public static void updateRestTestRequest(RestTestRequestStep restTestRequestStep) {
try {
RestRequestStepConfig restRequestStepConfig = (RestRequestStepConfig) restTestRequestStep.getConfig()
.getConfig();
RestRequestConfig restRequestConfig = restRequestStepConfig.getRestRequest();
OldRestRequestConfig oldConfig = OldRestRequestConfig.Factory.parse(restRequestConfig.toString());
RestParametersConfig oldParams = oldConfig.getParameters();
if (oldParams != null) {
StringToStringMapConfig newParams = restRequestConfig.addNewParameters();
for (RestParameterConfig oldParam : oldParams.getParameterList()) {
if (StringUtils.hasContent(oldParam.getValue())) {
Entry entry = newParams.addNewEntry();
entry.setKey(oldParam.getName());
entry.setValue(oldParam.getValue());
}
}
restRequestConfig.getParameters().getDomNode().getParentNode()
.removeChild(restRequestConfig.getParameters().getDomNode());
}
} catch (XmlException e) {
SoapUI.logError(e);
}
}
}