完成解析jmx文件逻辑
This commit is contained in:
parent
5457a369da
commit
b9f58a8910
|
@ -1,5 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum LoadTestFileType {
|
||||
public enum EngineType {
|
||||
JMX
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
package io.metersphere.engine;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EngineContext {
|
||||
private String engineId;
|
||||
private String engineType;
|
||||
private InputStream inputStream;
|
||||
private Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
public String getEngineId() {
|
||||
return engineId;
|
||||
|
@ -14,6 +18,14 @@ public class EngineContext {
|
|||
this.engineId = engineId;
|
||||
}
|
||||
|
||||
public String getEngineType() {
|
||||
return engineType;
|
||||
}
|
||||
|
||||
public void setEngineType(String engineType) {
|
||||
this.engineType = engineType;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
@ -21,4 +33,12 @@ public class EngineContext {
|
|||
public void setInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public void addProperty(String key, Object value) {
|
||||
this.properties.put(key, value);
|
||||
}
|
||||
|
||||
public Object getProperty(String key) {
|
||||
return this.properties.get(key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,54 @@
|
|||
package io.metersphere.engine;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.FileContent;
|
||||
import io.metersphere.base.domain.FileMetadata;
|
||||
import io.metersphere.base.domain.LoadTestWithBLOBs;
|
||||
import io.metersphere.commons.constants.LoadTestFileType;
|
||||
import io.metersphere.commons.constants.EngineType;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.engine.jmx.JmxEngine;
|
||||
import io.metersphere.parse.EngineSourceParser;
|
||||
import io.metersphere.parse.EngineSourceParserFactory;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class EngineFactory {
|
||||
public static Engine createEngine(String engineType) {
|
||||
final LoadTestFileType type = LoadTestFileType.valueOf(engineType);
|
||||
final EngineType type = EngineType.valueOf(engineType);
|
||||
|
||||
if (type == LoadTestFileType.JMX) {
|
||||
if (type == EngineType.JMX) {
|
||||
return new JmxEngine();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static EngineContext createContext(LoadTestWithBLOBs loadTest, FileContent fileContent) {
|
||||
public static EngineContext createContext(LoadTestWithBLOBs loadTest, FileMetadata fileMetadata, FileContent fileContent) throws Exception {
|
||||
final EngineContext engineContext = new EngineContext();
|
||||
engineContext.setEngineId(loadTest.getId());
|
||||
engineContext.setInputStream(new ByteArrayInputStream(fileContent.getFile().getBytes(StandardCharsets.UTF_8)));
|
||||
engineContext.setEngineType(fileMetadata.getType());
|
||||
|
||||
if (!StringUtils.isEmpty(loadTest.getLoadConfiguration())) {
|
||||
final JSONArray jsonArray = JSONObject.parseArray(loadTest.getLoadConfiguration());
|
||||
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
final JSONObject jsonObject = jsonArray.getJSONObject(i);
|
||||
engineContext.addProperty(jsonObject.getString("key"), jsonObject.get("value"));
|
||||
}
|
||||
}
|
||||
|
||||
final EngineSourceParser engineSourceParser = EngineSourceParserFactory.createEngineSourceParser(engineContext.getEngineType());
|
||||
|
||||
if (engineSourceParser == null) {
|
||||
MSException.throwException("未知的文件类型!");
|
||||
}
|
||||
|
||||
final InputStream inputStream = engineSourceParser.parse(engineContext, engineContext.getInputStream());
|
||||
engineContext.setInputStream(inputStream);
|
||||
|
||||
return engineContext;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package io.metersphere.parse;
|
||||
|
||||
import io.metersphere.engine.EngineContext;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface EngineSourceParser {
|
||||
InputStream parse(EngineContext context, InputStream source) throws Exception;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.parse;
|
||||
|
||||
import io.metersphere.commons.constants.EngineType;
|
||||
import io.metersphere.parse.xml.XmlEngineSourceParse;
|
||||
|
||||
public class EngineSourceParserFactory {
|
||||
public static EngineSourceParser createEngineSourceParser(String type) {
|
||||
final EngineType engineType = EngineType.valueOf(type);
|
||||
|
||||
if (EngineType.JMX.equals(engineType)) {
|
||||
return new XmlEngineSourceParse();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package io.metersphere.parse.xml;
|
||||
|
||||
import io.metersphere.engine.EngineContext;
|
||||
import io.metersphere.parse.EngineSourceParser;
|
||||
import io.metersphere.parse.xml.reader.DocumentParser;
|
||||
import io.metersphere.parse.xml.reader.DocumentParserFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class XmlEngineSourceParse implements EngineSourceParser {
|
||||
@Override
|
||||
public InputStream parse(EngineContext context, InputStream source) throws Exception {
|
||||
final InputSource inputSource = new InputSource(source);
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
|
||||
DocumentBuilder docBuilder = factory.newDocumentBuilder();
|
||||
final Document document = docBuilder.parse(inputSource);
|
||||
|
||||
final DocumentParser documentParser = createDocumentParser(context.getEngineType());
|
||||
|
||||
return documentParser.parse(context, document);
|
||||
}
|
||||
|
||||
private DocumentParser createDocumentParser(String type) {
|
||||
return DocumentParserFactory.createDocumentParser(type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package io.metersphere.parse.xml.reader;
|
||||
|
||||
import io.metersphere.engine.EngineContext;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface DocumentParser {
|
||||
InputStream parse(EngineContext context, Document document) throws Exception;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.parse.xml.reader;
|
||||
|
||||
import io.metersphere.commons.constants.EngineType;
|
||||
import io.metersphere.parse.xml.reader.jmx.JmeterDocumentParser;
|
||||
|
||||
public class DocumentParserFactory {
|
||||
public static DocumentParser createDocumentParser(String type) {
|
||||
final EngineType engineType = EngineType.valueOf(type);
|
||||
|
||||
if (EngineType.JMX.equals(engineType)) {
|
||||
return new JmeterDocumentParser();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package io.metersphere.parse.xml.reader.jmx;
|
||||
|
||||
import io.metersphere.engine.EngineContext;
|
||||
import io.metersphere.parse.xml.reader.DocumentParser;
|
||||
import org.junit.platform.commons.util.StringUtils;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
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.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class JmeterDocumentParser implements DocumentParser {
|
||||
private final static String HASH_TREE_ELEMENT = "hashTree";
|
||||
private final static String STRING_PROP = "stringProp";
|
||||
private final static String CONCURRENCY_THREAD_GROUP = "com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup";
|
||||
private EngineContext context;
|
||||
|
||||
@Override
|
||||
public InputStream parse(EngineContext context, Document document) throws Exception {
|
||||
this.context = context;
|
||||
|
||||
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;
|
||||
|
||||
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
||||
parseHashTree(ele);
|
||||
}
|
||||
}
|
||||
|
||||
return documentToInputStream(document);
|
||||
}
|
||||
|
||||
private InputStream documentToInputStream(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);
|
||||
final String resultStr = writer.toString();
|
||||
return new ByteArrayInputStream(resultStr.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
private 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, CONCURRENCY_THREAD_GROUP)) {
|
||||
processConcurrencyThreadGroup(ele);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processConcurrencyThreadGroup(Element concurrencyThreadGroup) {
|
||||
if (concurrencyThreadGroup.getChildNodes().getLength() > 0) {
|
||||
final NodeList childNodes = concurrencyThreadGroup.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, STRING_PROP)) {
|
||||
parseStringProp(ele);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseStringProp(Element stringProp) {
|
||||
if (stringProp.getChildNodes().getLength() > 0 && context.getProperty(stringProp.getAttribute("name")) != null) {
|
||||
stringProp.getFirstChild().setNodeValue(context.getProperty(stringProp.getAttribute("name")).toString());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean nodeNameEquals(Node node, String desiredName) {
|
||||
return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName());
|
||||
}
|
||||
|
||||
private boolean invalid(Element ele) {
|
||||
return !StringUtils.isBlank(ele.getAttribute("enabled")) && !Boolean.parseBoolean(ele.getAttribute("enabled"));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ package io.metersphere.service;
|
|||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
||||
import io.metersphere.commons.constants.LoadTestFileType;
|
||||
import io.metersphere.commons.constants.EngineType;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.IOUtils;
|
||||
import io.metersphere.controller.request.testplan.*;
|
||||
|
@ -108,7 +108,7 @@ public class LoadTestService {
|
|||
fileMetadata.setSize(file.getSize());
|
||||
fileMetadata.setCreateTime(System.currentTimeMillis());
|
||||
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
||||
fileMetadata.setType(LoadTestFileType.JMX.name());
|
||||
fileMetadata.setType(EngineType.JMX.name());
|
||||
fileMetadataMapper.insert(fileMetadata);
|
||||
|
||||
FileContent fileContent = new FileContent();
|
||||
|
@ -171,7 +171,12 @@ public class LoadTestService {
|
|||
fileMetadata.getType()));
|
||||
}
|
||||
|
||||
final boolean init = engine.init(EngineFactory.createContext(loadTest, fileContent));
|
||||
boolean init = true;
|
||||
try {
|
||||
init = engine.init(EngineFactory.createContext(loadTest, fileMetadata, fileContent));
|
||||
} catch (Exception e) {
|
||||
MSException.throwException(e);
|
||||
}
|
||||
if (!init) {
|
||||
MSException.throwException(String.format("无法运行测试,初始化运行环境失败,测试ID:%s", request.getId()));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
package io.metersphere;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.platform.commons.util.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.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.StringWriter;
|
||||
|
||||
public class JmxFileParseTest {
|
||||
private final static String HASH_TREE_ELEMENT = "hashTree";
|
||||
private final static String STRING_PROP = "stringProp";
|
||||
private final static String CONCURRENCY_THREAD_GROUP = "com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup";
|
||||
|
||||
@Test
|
||||
public void parse() throws Exception {
|
||||
File file = new File("/Users/dhf/Desktop/Concurrency Thread Group.jmx");
|
||||
|
||||
final FileInputStream inputStream = new FileInputStream(file);
|
||||
final InputSource inputSource = new InputSource(inputStream);
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
|
||||
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;
|
||||
|
||||
// jmeterTestPlan的子元素肯定是<hashTree></hashTree>
|
||||
parseHashTree(ele);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
System.out.println("XML IN String format is: \n" + writer.toString());
|
||||
}
|
||||
|
||||
private void parseHashTree(Element hashTree) {
|
||||
if (!valid(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 (!valid(ele)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nodeNameEquals(ele, HASH_TREE_ELEMENT)) {
|
||||
parseHashTree(ele);
|
||||
} else if (nodeNameEquals(ele, CONCURRENCY_THREAD_GROUP)) {
|
||||
processConcurrencyThreadGroup(ele);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processConcurrencyThreadGroup(Element concurrencyThreadGroup) {
|
||||
if (concurrencyThreadGroup.getChildNodes().getLength() > 0) {
|
||||
final NodeList childNodes = concurrencyThreadGroup.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element ele = (Element) node;
|
||||
if (!valid(ele)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nodeNameEquals(ele, STRING_PROP)) {
|
||||
parseStringProp(ele);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseStringProp(Element stringProp) {
|
||||
if (stringProp.getChildNodes().getLength() > 0) {
|
||||
stringProp.getFirstChild().setNodeValue("1");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean nodeNameEquals(Node node, String desiredName) {
|
||||
return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName());
|
||||
}
|
||||
|
||||
private boolean valid(Element ele) {
|
||||
return StringUtils.isBlank(ele.getAttribute("enabled")) || Boolean.parseBoolean(ele.getAttribute("enabled"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue