In memory compiler 로 변경, 기동시 스크립트 로딩 추가

This commit is contained in:
yunjy
2022-08-19 14:17:06 +09:00
parent 83568bd9d5
commit 9ce8bd619f
6 changed files with 58 additions and 31 deletions
+2
View File
@@ -22,11 +22,13 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
// implementation 'com.github.darrachequesne:spring-data-jpa-datatables:5.1.0' // implementation 'com.github.darrachequesne:spring-data-jpa-datatables:5.1.0'
implementation 'org.apache.commons:commons-lang3:3.10' implementation 'org.apache.commons:commons-lang3:3.10'
implementation 'commons-io:commons-io:2.6' implementation 'commons-io:commons-io:2.6'
implementation 'com.jayway.jsonpath:json-path:2.4.0' implementation 'com.jayway.jsonpath:json-path:2.4.0'
implementation 'io.netty:netty-all:4.1.60.Final' implementation 'io.netty:netty-all:4.1.60.Final'
runtimeOnly 'com.h2database:h2' runtimeOnly 'com.h2database:h2'
implementation 'org.mdkt.compiler:InMemoryJavaCompiler:1.3.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
} }
@@ -0,0 +1,28 @@
package com.eactive.httpmockserver;
import com.eactive.httpmockserver.script.ScriptInfoService;
import com.eactive.httpmockserver.script.ScriptLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class PostConstructBean {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
public ScriptInfoService scriptInfoService;
@PostConstruct
public void init() {
logger.info("init scripts");
try {
ScriptLoader.getInstance().init(scriptInfoService);
} catch (Exception e) {
logger.error("init scripts failed", e);
}
}
}
@@ -62,7 +62,7 @@ public class ScriptController {
} }
@PostMapping("/manage/saveScriptInfo") @PostMapping("/manage/saveScriptInfo")
public String saveScriptInfo(@Valid ScriptInfo spec, BindingResult result, Model model) throws IOException, ClassNotFoundException { public String saveScriptInfo(@Valid ScriptInfo spec, BindingResult result, Model model) throws Exception {
if (result.hasErrors()) { if (result.hasErrors()) {
return "page/add-edit-script-info"; return "page/add-edit-script-info";
} }
@@ -74,7 +74,7 @@ public class ScriptController {
} }
if (BooleanUtils.toBoolean(spec.getUseYn())) { if (BooleanUtils.toBoolean(spec.getUseYn())) {
// 기존설정 useYn=N으로 수정 // ±âÁ¸¼³Á¤ useYn=NÀ¸·Î ¼öÁ¤
scriptInfoService.setUnuseOthers(spec.getId()); scriptInfoService.setUnuseOthers(spec.getId());
} }
@@ -9,6 +9,8 @@ import java.util.Optional;
public interface ScriptInfoService { public interface ScriptInfoService {
public ScriptInfo findActiveScriptInfo(); public ScriptInfo findActiveScriptInfo();
public List<ScriptInfo> findAllScriptInfos();
public List<ScriptInfo> findAllScriptInfos(Pageable pageable); public List<ScriptInfo> findAllScriptInfos(Pageable pageable);
public List<ScriptInfo> findAllScriptInfos(Example<ScriptInfo> example, Pageable pageable); public List<ScriptInfo> findAllScriptInfos(Example<ScriptInfo> example, Pageable pageable);
@@ -23,6 +23,11 @@ public class ScriptInfoServiceImpl implements ScriptInfoService {
return dao.findFirstByUseYn("Y"); return dao.findFirstByUseYn("Y");
} }
@Override
public List<ScriptInfo> findAllScriptInfos() {
return dao.findAll();
}
@Override @Override
public List<ScriptInfo> findAllScriptInfos(Pageable pageable) { public List<ScriptInfo> findAllScriptInfos(Pageable pageable) {
Page<ScriptInfo> pagedResult = dao.findAll(pageable); Page<ScriptInfo> pagedResult = dao.findAll(pageable);
@@ -1,6 +1,8 @@
package com.eactive.httpmockserver.script; package com.eactive.httpmockserver.script;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.mdkt.compiler.InMemoryJavaCompiler;
import org.springframework.beans.factory.annotation.Autowired;
import javax.tools.JavaCompiler; import javax.tools.JavaCompiler;
import javax.tools.ToolProvider; import javax.tools.ToolProvider;
@@ -12,6 +14,7 @@ import java.lang.reflect.InvocationTargetException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class ScriptLoader{ public class ScriptLoader{
@@ -36,42 +39,29 @@ public class ScriptLoader{
return newInstance; return newInstance;
} }
class DynamicLoader extends ClassLoader{ // class DynamicLoader extends ClassLoader{
public Class<Script> loadScript(String fullClassName, byte[] classData){ // public Class<Script> loadScript(String fullClassName, byte[] classData){
return (Class<Script>) defineClass(fullClassName, // return (Class<Script>) defineClass(fullClassName,
classData, 0, classData.length); // classData, 0, classData.length);
// }
// }
public void init(ScriptInfoService scriptInfoService) throws Exception {
List<ScriptInfo> scriptInfoList = scriptInfoService.findAllScriptInfos();
for (ScriptInfo info :scriptInfoList) {
load(info.getScriptName(), info.getScriptCode());
} }
} }
public void load(String scriptName, String scriptCode) throws ClassNotFoundException, IOException { public void load(String scriptName, String scriptCode) throws Exception {
String source = scriptCode; String source = scriptCode;
String fullPath = DYNAMIC_BASE_PATH + "/" + scriptName;
String fullPackage = DYNAMIC_BASE_PACKAGE + "." + scriptName; String fullPackage = DYNAMIC_BASE_PACKAGE + "." + scriptName;
Class<Script> cls = (Class<Script>) InMemoryJavaCompiler.newInstance().compile(fullPackage, source);
File packagePath = new File(path + DYNAMIC_BASE_PATH); // Script newInstance = cls.getDeclaredConstructor().newInstance();
if(!packagePath.exists()) // String xx = newInstance.postProcess("abc","ddd");
packagePath.mkdirs(); // System.out.println(xx);
File sourceFile = new File(path + fullPath + ".java");
new FileWriter(sourceFile).append(source).close();
// 만들어진 Java 파일을 컴파일한다.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, System.out, System.out, sourceFile.getPath());
// File classPath = new File(path + DYNAMIC_BASE_PATH);
// 컴파일된 Class를 Load
// URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] {classPath.toURI().toURL()});
// Class<Script> cls = (Class<Script>) Class.forName(fullPackage, true, classLoader);
// new File(path + DYNAMIC_BASE_PATH + "/" + scriptName +".class").delete();
// sourceFile.delete();
File classFile = new File(path + DYNAMIC_BASE_PATH + "/" + scriptName +".class");
byte[] classData = IOUtils.toByteArray(new FileInputStream(classFile));
DynamicLoader dynamicLoader = new DynamicLoader();
Class<Script> cls = dynamicLoader.loadScript(fullPackage, classData);
this.loadedClass.put(scriptName, cls); this.loadedClass.put(scriptName, cls);
} }