package org.wiztools.restclient.persistence;
import java.io.File;
import java.io.IOException;
import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.ParsingException;
import org.wiztools.commons.StringUtil;
import org.wiztools.restclient.Versions;
import org.wiztools.restclient.bean.CookieVersion;
import org.wiztools.restclient.bean.HTTPMethod;
import org.wiztools.restclient.bean.HTTPVersion;
import org.wiztools.restclient.bean.ReqEntity;
import org.wiztools.restclient.bean.Request;
import org.wiztools.restclient.bean.RequestBean;
import org.wiztools.restclient.bean.Response;
import org.wiztools.restclient.bean.ResponseBean;
import org.wiztools.restclient.bean.TestResultBean;
import org.wiztools.restclient.util.Util;
/**
*
* @author subwiz
*/
public class XmlPersistenceRead implements PersistenceRead {
private String readVersion;
public void setReadVersion(String version) {
readVersion = version;
}
private Map<String, String> getHeadersFromHeaderNode(final Element node)
throws XMLException {
Map<String, String> m = new LinkedHashMap<>();
for (int i = 0; i < node.getChildElements().size(); i++) {
Element headerElement = node.getChildElements().get(i);
if (!"header".equals(headerElement.getQualifiedName())) {
throw new XMLException("<headers> element should contain only <header> elements");
}
m.put(headerElement.getAttributeValue("key"),
headerElement.getAttributeValue("value"));
}
return m;
}
private List<HttpCookie> getCookiesFromCookiesNode(final Element node)
throws XMLException {
List<HttpCookie> out = new ArrayList<>();
for (int i = 0; i < node.getChildElements().size(); i++) {
Element e = node.getChildElements().get(i);
if(!"cookie".equals(e.getQualifiedName())) {
throw new XMLException("<cookies> element should contain only <cookie> elements");
}
HttpCookie cookie = new HttpCookie(e.getAttributeValue("name"),
e.getAttributeValue("value"));
final String cookieVerStr = e.getAttributeValue("version");
if(StringUtil.isNotEmpty(cookieVerStr)) {
cookie.setVersion(Integer.parseInt(cookieVerStr));
}
else {
cookie.setVersion(CookieVersion.DEFAULT_VERSION.getIntValue());
}
out.add(cookie);
}
return out;
}
protected Request getRequestBean(Element requestNode)
throws MalformedURLException, XMLException {
RequestBean requestBean = new RequestBean();
for (int i = 0; i < requestNode.getChildElements().size(); i++) {
Element tNode = requestNode.getChildElements().get(i);
String nodeName = tNode.getQualifiedName();
if ("http-version".equals(nodeName)) {
String t = tNode.getValue();
HTTPVersion httpVersion = "1.1".equals(t)?
HTTPVersion.HTTP_1_1 : HTTPVersion.HTTP_1_0;
requestBean.setHttpVersion(httpVersion);
}
else if("http-follow-redirects".equals(nodeName)) {
requestBean.setFollowRedirect(true);
}
else if("ignore-response-body".equals(nodeName)) {
requestBean.setIgnoreResponseBody(true);
}
else if ("URL".equals(nodeName)) {
URL url = new URL(tNode.getValue());
requestBean.setUrl(url);
}
else if ("method".equals(nodeName)) {
requestBean.setMethod(HTTPMethod.get(tNode.getValue()));
}
else if("auth".equals(nodeName)) {
requestBean.setAuth(XmlAuthUtil.getAuth(tNode));
}
else if("ssl".equals(nodeName)) {
requestBean.setSslReq(XmlSslUtil.getSslReq(tNode));
}
else if ("headers".equals(nodeName)) {
Map<String, String> m = getHeadersFromHeaderNode(tNode);
for (String key : m.keySet()) {
requestBean.addHeader(key, m.get(key));
}
}
else if ("cookies".equals(nodeName)) {
List<HttpCookie> cookies = getCookiesFromCookiesNode(tNode);
for (HttpCookie cookie: cookies) {
requestBean.addCookie(cookie);
}
}
else if ("body".equals(nodeName)) {
XmlBodyRead bdUtl = new XmlBodyRead(readVersion);
ReqEntity body = bdUtl.getReqEntity(tNode);
requestBean.setBody(body);
}
else if ("test-script".equals(nodeName)) {
requestBean.setTestScript(tNode.getValue());
}
else {
throw new XMLException("Invalid element encountered: <" + nodeName + ">");
}
}
return requestBean;
}
protected Request xml2Request(final Document doc)
throws MalformedURLException, XMLException {
// get the rootNode
Element rootNode = doc.getRootElement();
if (!"rest-client".equals(rootNode.getQualifiedName())) {
throw new XMLException("Root node is not <rest-client>");
}
// checking correct rest version
final String rcVersion = rootNode.getAttributeValue("version");
try {
Versions.versionValidCheck(rcVersion);
}
catch(Versions.VersionValidationException ex) {
throw new XMLException(ex);
}
readVersion = rcVersion;
// if more than two request element is present then throw the exception
if (rootNode.getChildElements().size() != 1) {
throw new XMLException("There can be only one child node for root node: <request>");
}
// minimum one request element is present in xml
if (rootNode.getFirstChildElement("request") == null) {
throw new XMLException("The child node of <rest-client> should be <request>");
}
Element requestNode = rootNode.getFirstChildElement("request");
return getRequestBean(requestNode);
}
protected Response xml2Response(final Document doc)
throws XMLException {
ResponseBean responseBean = new ResponseBean();
// get the rootNode
Element rootNode = doc.getRootElement();
if (!"rest-client".equals(rootNode.getQualifiedName())) {
throw new XMLException("Root node is not <rest-client>");
}
// checking correct rest version
try {
Versions.versionValidCheck(rootNode.getAttributeValue("version"));
}
catch(Versions.VersionValidationException ex) {
throw new XMLException(ex);
}
// assign rootnode to current node and also finding 'response' node
Element tNode = null;
Element responseNode = null;
// if more than two request element is present then throw the exception
if (rootNode.getChildElements().size() != 1) {
throw new XMLException("There can be only one child node for root node: <response>");
}
// minimum one response element is present in xml
if (rootNode.getFirstChildElement("response") == null) {
throw new XMLException("The child node of <rest-client> should be <response>");
}
responseNode = rootNode.getFirstChildElement("response");
for (int i = 0; i < responseNode.getChildElements().size(); i++) {
tNode = responseNode.getChildElements().get(i);
String nodeName = tNode.getQualifiedName();
if ("execution-time".equals(nodeName)) {
responseBean.setExecutionTime(Long.parseLong(tNode.getValue()));
} else if ("status".equals(nodeName)) {
responseBean.setStatusLine(tNode.getValue());
responseBean.setStatusCode(Integer.parseInt(tNode.getAttributeValue("code")));
} else if ("headers".equals(nodeName)) {
Map<String, String> m = getHeadersFromHeaderNode(tNode);
for (String key : m.keySet()) {
responseBean.addHeader(key, m.get(key));
}
} else if ("body".equals(nodeName)) {
final String base64body = tNode.getValue();
responseBean.setResponseBody(Util.base64decodeByteArray(base64body));
} else if ("test-result".equals(nodeName)) {
TestResultBean testResultBean = new TestResultBean();
for (int j = 0; j < tNode.getChildCount(); j++) {
String nn = tNode.getQualifiedName();
if ("run-count".equals(nn)) {
throw new XMLException("<headers> element should contain only <header> elements");
} else if ("failure-count".equals(nn)) {
throw new XMLException("<headers> element should contain only <header> elements");
} else if ("error-count".equals(nn)) {
throw new XMLException("<headers> element should contain only <header> elements");
} else if ("failures".equals(nn)) {
throw new XMLException("<headers> element should contain only <header> elements");
} else if ("errors".equals(nn)) {
throw new XMLException("<headers> element should contain only <header> elements");
}
}
responseBean.setTestResult(testResultBean);
} else {
throw new XMLException("Unrecognized element found: <" + nodeName + ">");
}
}
return responseBean;
}
protected Document getDocumentFromFile(final File f)
throws IOException, XMLException {
try {
Builder parser = new Builder();
Document doc = parser.build(f);
return doc;
}
catch (ParsingException | IOException ex) {
throw new XMLException(ex.getMessage(), ex);
}
}
@Override
public Request getRequestFromFile(final File f)
throws IOException, PersistenceException {
Document doc = getDocumentFromFile(f);
return xml2Request(doc);
}
@Override
public Response getResponseFromFile(final File f)
throws IOException, PersistenceException {
Document doc = getDocumentFromFile(f);
return xml2Response(doc);
}
}