From b4ed0a5d613eafb2f32bbd8aab5743e63f0621c8 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Mon, 17 Aug 2020 12:28:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=90=8E=E5=8F=B0=E5=A4=84?= =?UTF-8?q?=E7=90=86mock=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/parse/JmeterDocumentParser.java | 224 ++++++++++++++++++ .../api/parse/JmxDocumentParser.java | 125 ---------- .../api/service/APITestService.java | 4 +- .../commons/utils/ScriptEngineUtils.java | 2 +- 4 files changed, 227 insertions(+), 128 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/parse/JmeterDocumentParser.java delete mode 100644 backend/src/main/java/io/metersphere/api/parse/JmxDocumentParser.java diff --git a/backend/src/main/java/io/metersphere/api/parse/JmeterDocumentParser.java b/backend/src/main/java/io/metersphere/api/parse/JmeterDocumentParser.java new file mode 100644 index 0000000000..6f69d977f1 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/parse/JmeterDocumentParser.java @@ -0,0 +1,224 @@ +package io.metersphere.api.parse; + +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.commons.utils.ScriptEngineUtils; +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +public class JmeterDocumentParser { + private final static String HASH_TREE_ELEMENT = "hashTree"; + private final static String STRING_PROP = "stringProp"; + private final static String ARGUMENTS = "Arguments"; + private final static String COLLECTION_PROP = "collectionProp"; + private final static String HTTP_SAMPLER_PROXY = "HTTPSamplerProxy"; + private final static String ELEMENT_PROP = "elementProp"; + + public static byte[] parse(byte[] source) { + final InputSource inputSource = new InputSource(new ByteArrayInputStream(source)); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try { + + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + final Document document = docBuilder.parse(inputSource); + final Element jmeterTestPlan = document.getDocumentElement(); + + NodeList childNodes = jmeterTestPlan.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if (node instanceof Element) { + Element ele = (Element) node; + parseHashTree(ele); + } + } + return documentToBytes(document); + } catch (Exception e) { + LogUtil.error(e); + return source; + } + } + + private static byte[] documentToBytes(Document document) throws TransformerException { + DOMSource domSource = new DOMSource(document); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.transform(domSource, result); + return writer.toString().getBytes(); + } + + private static void parseHashTree(Element hashTree) { + if (invalid(hashTree)) { + return; + } + + if (hashTree.getChildNodes().getLength() > 0) { + final NodeList childNodes = hashTree.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if (node instanceof Element) { + Element ele = (Element) node; + if (invalid(ele)) { + continue; + } + + if (nodeNameEquals(ele, HASH_TREE_ELEMENT)) { + parseHashTree(ele); + } else if (nodeNameEquals(ele, ARGUMENTS)) { + processArguments(ele); + } else if (nodeNameEquals(ele, HTTP_SAMPLER_PROXY)) { + processHttpSamplerProxy(ele); + } + } + } + } + } + + private static void processHttpSamplerProxy(Element ele) { + if (invalid(ele)) { + return; + } + NodeList childNodes = ele.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.item(i); + if (!(item instanceof Element)) { + continue; + } + Element element = (Element) item; + if (nodeNameEquals(element, ELEMENT_PROP) && "HTTPsampler.Arguments".equals(element.getAttribute("name"))) { + processArguments(element); + } else if ("HTTPSampler.path".equals(element.getAttribute("name"))) { + processStringProp(element); + } + } + } + + private static void processArguments(Element ele) { + if (invalid(ele)) { + return; + } + NodeList childNodes = ele.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.item(i); + if (!(item instanceof Element)) { + continue; + } + Element element = (Element) item; + if (nodeNameEquals(item, COLLECTION_PROP) && "Arguments.arguments".equals(element.getAttribute("name"))) { + NodeList elementProps = item.getChildNodes(); + for (int j = 0; j < elementProps.getLength(); j++) { + Node elementProp = elementProps.item(j); + if (!(elementProp instanceof Element)) { + continue; + } + NodeList stringProps = elementProp.getChildNodes(); + for (int k = 0; k < stringProps.getLength(); k++) { + Node stringProp = stringProps.item(k); + if (!(stringProp instanceof Element)) { + continue; + } + processStringProp((Element) stringProp); + } + } + } + } + } + + private static void processStringProp(Element ele) { + String name = ele.getAttribute("name"); + switch (name) { + case "HTTPSampler.path": + String path = ele.getTextContent(); + Map parser = parserUrl(path); + String url = parser.get("URL"); + String params = parser.keySet().stream().filter(k -> !"URL".equals(k)).reduce("", (u, k) -> { + String v = parser.get(k); + u += "&" + k + "=" + ScriptEngineUtils.calculate(v); + return u; + }); + ele.setTextContent(url + params); + break; + case "Argument.value": + String textContent = ele.getTextContent(); + System.out.println(textContent); + ele.setTextContent(ScriptEngineUtils.calculate(textContent)); + break; + default: + break; + } + } + + private static boolean nodeNameEquals(Node node, String desiredName) { + return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName()); + } + + private static boolean invalid(Element ele) { + return !StringUtils.isBlank(ele.getAttribute("enabled")) && !Boolean.parseBoolean(ele.getAttribute("enabled")); + } + + private static Map parserUrl(String url) { +// 传递的URL参数 + Map strUrlParas = new HashMap<>(); + + String strUrl; + String strUrlParams; + + +// 解析访问地址 + if (url.contains("?")) { + String[] strUrlPatten = url.split("\\?"); + strUrl = strUrlPatten[0]; + strUrlParams = strUrlPatten[1]; + + } else { + strUrl = url; + strUrlParams = url; + } + + strUrlParas.put("URL", strUrl); +// 解析参数 + String[] params = null; + + if (strUrlParams.contains("&")) { + params = strUrlParams.split("&"); + } else { + params = new String[]{strUrlParams}; + } + +// 保存参数到参数容器 + for (String p : params) { + if (p.contains("=")) { + String[] param = p.split("="); + if (param.length == 1) { + strUrlParas.put(param[0], ""); + } else { + + String key = param[0]; + String value = param[1]; + + strUrlParas.put(key, value); + } + } else { + strUrlParas.put("errorParam", p); + } + } + return strUrlParas; + } +} diff --git a/backend/src/main/java/io/metersphere/api/parse/JmxDocumentParser.java b/backend/src/main/java/io/metersphere/api/parse/JmxDocumentParser.java deleted file mode 100644 index 5f1103cf5d..0000000000 --- a/backend/src/main/java/io/metersphere/api/parse/JmxDocumentParser.java +++ /dev/null @@ -1,125 +0,0 @@ -package io.metersphere.api.parse; - -import io.metersphere.commons.utils.LogUtil; -import io.metersphere.commons.utils.ScriptEngineUtils; -import org.apache.commons.lang3.StringUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.ByteArrayInputStream; -import java.io.StringWriter; - -public class JmxDocumentParser { - private final static String HASH_TREE_ELEMENT = "hashTree"; - private final static String STRING_PROP = "stringProp"; - - public static byte[] parse(byte[] source) { - final InputSource inputSource = new InputSource(new ByteArrayInputStream(source)); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - try { - - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - final Document document = docBuilder.parse(inputSource); - final Element jmeterTestPlan = document.getDocumentElement(); - - NodeList childNodes = jmeterTestPlan.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if (node instanceof Element) { - Element ele = (Element) node; - parseHashTree(ele); - } - } - return documentToBytes(document); - } catch (Exception e) { - LogUtil.error(e); - return source; - } - } - - private static byte[] documentToBytes(Document document) throws TransformerException { - DOMSource domSource = new DOMSource(document); - StringWriter writer = new StringWriter(); - StreamResult result = new StreamResult(writer); - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer transformer = tf.newTransformer(); - transformer.transform(domSource, result); - return writer.toString().getBytes(); - } - - private static void parseHashTree(Element hashTree) { - if (invalid(hashTree)) { - return; - } - - if (hashTree.getChildNodes().getLength() > 0) { - final NodeList childNodes = hashTree.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if (node instanceof Element) { - Element ele = (Element) node; - if (invalid(ele)) { - continue; - } - - if (nodeNameEquals(ele, HASH_TREE_ELEMENT)) { - parseHashTree(ele); - } else { - if (nodeNameEquals(ele, STRING_PROP)) { - processStringProp(ele); - } - } - } - } - } - } - - private static void processStringProp(Element ele) { - String name = ele.getAttribute("name"); - NodeList childNodes; - switch (name) { - case "HTTPSampler.path": - childNodes = ele.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if (node instanceof Element) { - String nodeValue = node.getNodeValue(); - System.out.println(nodeValue); - } - } - break; - case "Argument.value": - childNodes = ele.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if (node instanceof Element) { - String nodeValue = node.getNodeValue(); - node.setNodeValue(ScriptEngineUtils.calculate(nodeValue)); - } - } - break; - default: - break; - } - } - - private static boolean nodeNameEquals(Node node, String desiredName) { - return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName()); - } - - private static boolean invalid(Element ele) { - return !StringUtils.isBlank(ele.getAttribute("enabled")) && !Boolean.parseBoolean(ele.getAttribute("enabled")); - } - -} diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index 4dad243152..5be5432778 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -8,7 +8,7 @@ import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.parse.ApiImportParser; import io.metersphere.api.parse.ApiImportParserFactory; -import io.metersphere.api.parse.JmxDocumentParser; +import io.metersphere.api.parse.JmeterDocumentParser; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiTestFileMapper; import io.metersphere.base.mapper.ApiTestMapper; @@ -150,7 +150,7 @@ public class APITestService { } byte[] bytes = fileService.loadFileAsBytes(file.getFileId()); // 解析 xml 处理 mock 数据 - bytes = JmxDocumentParser.parse(bytes); + bytes = JmeterDocumentParser.parse(bytes); InputStream is = new ByteArrayInputStream(bytes); APITestResult apiTest = get(request.getId()); diff --git a/backend/src/main/java/io/metersphere/commons/utils/ScriptEngineUtils.java b/backend/src/main/java/io/metersphere/commons/utils/ScriptEngineUtils.java index e169671ce9..138d01c655 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/ScriptEngineUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/ScriptEngineUtils.java @@ -24,7 +24,7 @@ public class ScriptEngineUtils { public static String calculate(String input) { try { - return engine.eval(input).toString(); + return engine.eval("calculate('" + input + "')").toString(); } catch (ScriptException e) { LogUtil.error(e); return input;