From d76f816e927897a70a94292c73575191defe43ce Mon Sep 17 00:00:00 2001 From: CaiHQ Date: Tue, 6 Jun 2023 17:54:57 +0800 Subject: [PATCH] support interface support ResultSchema --- build.gradle | 8 +- .../java/org/bdware/sc/ContractProcess.java | 12 ++- .../org/bdware/sc/compiler/YJSCompiler.java | 30 +++++-- .../sc/engine/hook/ArgSchemaHandler.java | 1 + .../sc/engine/hook/ArgSchemaVisitor.java | 9 +- .../sc/engine/hook/DOOPAfterExecHandler.java | 8 +- .../sc/engine/hook/DOOPBeforeExecHandler.java | 1 + .../sc/engine/hook/ResultSchemaHandler.java | 84 +++++++++++++++++++ .../bdware/sc/handler/DOOPRequestHandler.java | 4 +- .../java/org/bdware/sc/memory/MemoryDump.java | 1 + 10 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 src/main/java/org/bdware/sc/engine/hook/ResultSchemaHandler.java diff --git a/build.gradle b/build.gradle index b18c757..11fa2e8 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = "org.bdware.sc" -version = "1.8.9" +version = "1.9.0" tasks.withType(JavaCompile) { // options.compilerArgs << '-Xlint:none' // options.compilerArgs << '-Xlint:deprecation' << "-Werror" @@ -48,8 +48,8 @@ dependencies { implementation 'com.sun.mail:javax.mail:1.6.2' implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation 'org.bdware.bdcontract:sdk-java:1.0.2' - implementation 'org.bdware.doip:doip-audit-tool:1.2.6' - implementation 'org.bdware.doip:doip-sdk:1.4.2' + implementation 'org.bdware.doip:doip-audit-tool:1.2.9' + implementation 'org.bdware.doip:doip-sdk:1.4.4' implementation fileTree(dir: 'lib', include: '*.jar') testImplementation 'junit:junit:4.13.2' } @@ -68,7 +68,7 @@ jar { // while develop at local use "false" configurations.runtimeClasspath.filter { it.getAbsolutePath().contains("/lib/") - // false + //false }.collect { it.isDirectory() ? it : zipTree(it) } diff --git a/src/main/java/org/bdware/sc/ContractProcess.java b/src/main/java/org/bdware/sc/ContractProcess.java index 03eae2f..5f1d41e 100644 --- a/src/main/java/org/bdware/sc/ContractProcess.java +++ b/src/main/java/org/bdware/sc/ContractProcess.java @@ -473,13 +473,14 @@ public class ContractProcess { JavaScriptEntry.shardingID = this.contract.getShardingId(); // 设置javaScriptEntry中的shardingID // JavaScriptEntry + // contract.getCreateParam().get("repoId").getAsString()-->去获取repoId。 + //知道自己的BDOID --> repo的id。+contract.getID() String zipPath = contract.getScriptStr(); if (isArchiveFile(new File(zipPath))) { ZipFile zf = new ZipFile(zipPath); ContractZipBundle zipBundle = new YJSCompiler().compile(zf); cn = zipBundle.mergeContractNode(); // check functionNodes - List functionNodes = cn.getFunctions(); injectHandlers(); this.contract.setYjsType(cn.getYjsType()); @@ -569,6 +570,7 @@ public class ContractProcess { fun.appendBeforeInvokeHandler(argSchemaHandler); } + if (fun.isExport()) { //if(fun.annotations...) AccessHandler accessHandler = createHandlerIfExist(fun, AccessHandler.class); @@ -576,6 +578,10 @@ public class ContractProcess { fun.appendBeforeInvokeHandler(accessHandler); } fun.appendAfterInvokeHandler(new ObjToJsonHandler()); + ResultSchemaHandler resultSchemaHandler = createHandlerIfExist(fun, ResultSchemaHandler.class); + if (resultSchemaHandler != null) { + fun.appendAfterInvokeHandler(resultSchemaHandler); + } // fun.appendBeforeInvokeHandler(new ReadMeHandler()); // Mask是用于返回真正结果之后,做一些偏移,以保护数据隐私。 // if (fun.isMask()) { @@ -584,7 +590,7 @@ public class ContractProcess { // engine.getResources().loadAsString("/maskConfig.json"); // System.out.println("injectMask"+maskConfig); // System.out.println("injectMask"+this.contract.Mask); - fun.appendAfterInvokeHandler(new MaskHandler()); + // fun.appendAfterInvokeHandler(new MaskHandler()); // } } if (fun.isHomomorphicEncrypt()) { @@ -728,7 +734,7 @@ public class ContractProcess { startPort = arg.getAsJsonObject().get("doipStartPort").getAsInt(); } LOGGER.info("Fetch the onStartingDoipServerRes from router successfully, the result is " + onStartingDoipServerRes); - int doipListenPort = DoipClusterServer.startDoipServer(startPort,onStartingDoipServerRes); + int doipListenPort = DoipClusterServer.startDoipServer(startPort, onStartingDoipServerRes); returnValue.addProperty("doipListenPort", doipListenPort); this.contract.setDoipPort(doipListenPort); returnValue.addProperty("doipStartPort", startPort); diff --git a/src/main/java/org/bdware/sc/compiler/YJSCompiler.java b/src/main/java/org/bdware/sc/compiler/YJSCompiler.java index e69437d..f851bf4 100644 --- a/src/main/java/org/bdware/sc/compiler/YJSCompiler.java +++ b/src/main/java/org/bdware/sc/compiler/YJSCompiler.java @@ -5,13 +5,11 @@ import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.DiagnosticErrorListener; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.bdware.doip.audit.EndpointConfig; import org.bdware.sc.engine.YJSFilter; import org.bdware.sc.node.*; import org.bdware.sc.parser.JavaScriptLexer; import org.bdware.sc.parser.YJSParser; import org.bdware.sc.parser.YJSParser.ProgramContext; -import org.bdware.sc.server.DoipClusterServer; import org.bdware.sc.util.JsonUtil; import org.bdware.sc.visitor.ContractReader; import wrp.jdk.nashorn.internal.objects.Global; @@ -23,6 +21,7 @@ import wrp.jdk.nashorn.internal.runtime.options.Options; import java.io.*; import java.nio.charset.StandardCharsets; +import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -127,12 +126,18 @@ public class YJSCompiler { Set toParse = new HashSet<>(); toParse.add(cm.main); Set todo = new HashSet<>(); + Set allEntries = new HashSet<>(); + Enumeration iter = zf.entries(); + for (; iter.hasMoreElements(); ) { + ZipEntry ele = iter.nextElement(); + if (ele != null) + allEntries.add(ele.getName()); + } while (toParse.size() > 0) { for (String str : toParse) { if (czb.containsPath(str)) { continue; } - ZipEntry entry = zf.getEntry(str.startsWith("/") ? str : "/" + str); if (null == entry) { throw new IllegalStateException("missing import:" + str); @@ -140,7 +145,9 @@ public class YJSCompiler { ContractNode cn = compile(zf.getInputStream(entry), str); czb.put(str, cn); for (ImportNode in : cn.getImports()) { - todo.add(in.getPath()); + for (String enstr : allEntries) + if (enstr.startsWith(in.getPath()) && enstr.endsWith(".yjs")) + todo.add(enstr); } } toParse.clear(); @@ -173,7 +180,9 @@ public class YJSCompiler { compile(new ByteArrayInputStream(globalBeanContract.getBytes(StandardCharsets.UTF_8)), globalBeanName + ".yjs")); LOGGER.info("--compile-- " + globalBeanName); - + czb.setMergedContractNode(); + ContractNode node = czb.mergeContractNode(); + handleFunctionAnnotation(node); return czb; } @@ -193,17 +202,22 @@ public class YJSCompiler { contract = reader.visitProgram(tree); // 遍历完 获取 contract 里的 yjs type contract.initPlainText(cts); - handleAnnotation(contract);//处理注解 + handleModuleAnnotation(contract);//处理注解 + handleFunctionAnnotation(contract); return contract; } - private void handleAnnotation(ContractNode contractNode) throws Exception { + private void handleModuleAnnotation(ContractNode contractNode) throws Exception { for (AnnotationNode node : contract.annotations) { AnnotationProcessor processor = findProcessor(node); if (processor != null) { processor.processContract(node, contractNode); } } + + } + + private void handleFunctionAnnotation(ContractNode contractNode) throws Exception { for (FunctionNode functionNode : contractNode.getFunctions()) { List annos = functionNode.annotations;//函数里的annotation if (annos != null) @@ -215,7 +229,7 @@ public class YJSCompiler { } } - private AnnotationProcessor findProcessor(AnnotationNode node) { + public static AnnotationProcessor findProcessor(AnnotationNode node) { try { String clzName = YJSCompiler.class.getPackage().getName(); clzName += ".ap." + node.getType(); diff --git a/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java index 019e6df..cee4794 100644 --- a/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java +++ b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaHandler.java @@ -65,6 +65,7 @@ public class ArgSchemaHandler implements AnnotationHook { JsonObject jo = new JsonObject(); jo.addProperty("msg", visitor.getException()); jo.addProperty("code", visitor.errorCode); + jo.add("argSchema",JsonParser.parseString(a.getArgs().get(0))); throw new ScriptReturnException(jo); } return argPacks; diff --git a/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java index 14ac8f0..6adcdc6 100644 --- a/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java +++ b/src/main/java/org/bdware/sc/engine/hook/ArgSchemaVisitor.java @@ -1,9 +1,6 @@ package org.bdware.sc.engine.hook; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; +import com.google.gson.*; import org.bdware.mockjava.JsonVisitor; public class ArgSchemaVisitor extends JsonVisitor { @@ -37,12 +34,12 @@ public class ArgSchemaVisitor extends JsonVisitor { } status &= visitor.status; } else { - message += "[Missing argument] " + key.substring(1) + " should be supplied "; + message += "[Missing key] " + key.substring(1) + " should be supplied "; status = false; errorCode = 1002; } } else { - if (jo.has(key)) { + if (jo.has(key) && jo.get(key) != null && jo.get(key) != JsonNull.INSTANCE) { ArgSchemaVisitor visitor = new ArgSchemaVisitor(jo.get(key)); visitor.visit(schema.get(key)); if (!visitor.status) { diff --git a/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java b/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java index ff111d4..8808a0f 100644 --- a/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java @@ -43,8 +43,10 @@ public class DOOPAfterExecHandler implements AnnotationHook { if (!(argPacks.ret instanceof DoipMessage)) { JsonObject jsonObjectRes = ((JsonElement) argPacks.ret).getAsJsonObject(); if (!jsonObjectRes.has("bodyBase64Encoded") || jsonObjectRes.get("bodyBase64Encoded").getAsBoolean() == false) { - String body = jsonObjectRes.get("body").getAsString(); - jsonObjectRes.addProperty("body", ByteUtil.encodeBASE64(body.getBytes(StandardCharsets.UTF_8))); + if (jsonObjectRes.has("body")) { + String body = jsonObjectRes.get("body").getAsString(); + jsonObjectRes.addProperty("body", ByteUtil.encodeBASE64(body.getBytes(StandardCharsets.UTF_8))); + } } // validate json response ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonObjectRes); @@ -69,7 +71,7 @@ public class DOOPAfterExecHandler implements AnnotationHook { case Search: case ListOps: case Delete: - return JsonParser.parseString("{\"!header\":{\"!response\":\"string\",\"attributes\":{}},\"body\":\"string\"}"); + return JsonParser.parseString("{\"header\":{\"response\":\"string\",\"attributes\":{}},\"body\":\"string\"}"); case Extension: case Unknown: default: diff --git a/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java b/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java index d1cf7d5..738dd33 100644 --- a/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java @@ -38,6 +38,7 @@ public class DOOPBeforeExecHandler implements AnnotationHook { // set doipMsgPackerArg struct's params doipMsgPackerArg.setSource("http"); doipMsgPackerArg.rawDoipMsg = convertHttpRequestToDoipMessage(httpReq); + if (httpReq.verifySignature()) { doipMsgPackerArg.rawDoipMsg.credential = new MessageCredential(httpReq.getRequester(), new byte[0]); } else { diff --git a/src/main/java/org/bdware/sc/engine/hook/ResultSchemaHandler.java b/src/main/java/org/bdware/sc/engine/hook/ResultSchemaHandler.java new file mode 100644 index 0000000..4bfcce7 --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/ResultSchemaHandler.java @@ -0,0 +1,84 @@ +package org.bdware.sc.engine.hook; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.doip.codec.JsonDoipMessage; +import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.sc.JSEngine; +import org.bdware.sc.boundry.ScriptReturnException; +import org.bdware.sc.node.AnnotationHook; +import org.bdware.sc.node.AnnotationNode; +import org.bdware.sc.node.ArgPacks; +import org.bdware.sc.node.FunctionNode; +import org.bdware.sc.util.JsonUtil; + +@YJSAnnotation(name = "ResultSchema") +public class ResultSchemaHandler implements AnnotationHook { + private AnnotationNode a; + private static final Logger LOGGER = LogManager.getLogger(ResultSchemaHandler.class); + + public ResultSchemaHandler(AnnotationNode annotationNode) { + a = annotationNode; + } + + @Override + public ArgPacks handle(JSEngine desktopEngine, ArgPacks argPacks) throws ScriptReturnException { + Object ret = argPacks.ret; + if (ret != null) { + JsonElement je = null; + if (ret instanceof DoipMessage) { + JsonDoipMessage jo = JsonDoipMessage.fromDoipMessage((DoipMessage) ret); + je = JsonUtil.parseObjectAsJsonObject(jo); + } else if (ret instanceof JsonElement) { + je = (JsonElement) ret; + } + if (je == null) { + JsonObject jo = new JsonObject(); + jo.addProperty("msg", "[Illegal Type] result should not be empty or null"); + jo.addProperty("code", 1004); + throw new ScriptReturnException(jo); + } + ArgSchemaVisitor visitor; + if (je.isJsonObject()) + visitor = new ArgSchemaVisitor(je.getAsJsonObject()); + else { + try { + JsonElement obj = JsonParser.parseString(je.getAsString()); + visitor = new ArgSchemaVisitor(obj); + //IMPORTANT automatically convert arg type here + argPacks.ret = obj; + } catch (Exception e) { + e.printStackTrace(); + JsonObject jo = new JsonObject(); + jo.addProperty("msg", "[Illegal Type] result should be JSON"); + jo.add("errorResult", je); + jo.addProperty("code", 1004); + throw new ScriptReturnException(jo); + } + } + if (je.toString().isEmpty() && !a.getArgs().get(0).equals("")) { + JsonObject jo = new JsonObject(); + jo.addProperty("msg", "[Empty result] result should not be empty"); + jo.addProperty("code", 1003); + throw new ScriptReturnException(jo); + } + visitor.visit(JsonParser.parseString(a.getArgs().get(0))); + if (!visitor.getStatus()) { + JsonObject jo = new JsonObject(); + jo.addProperty("msg", visitor.getException()); + jo.addProperty("code", visitor.errorCode); + jo.add("errorResult", je); + jo.add("resultSchema", JsonParser.parseString(a.getArgs().get(0))); + throw new ScriptReturnException(jo); + } + } + return argPacks; + } + + public static ResultSchemaHandler fromAnnotationNode(FunctionNode funNode, AnnotationNode annoNode) { + return new ResultSchemaHandler(annoNode); + } +} diff --git a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java index cc1e5ea..73d27fd 100644 --- a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java +++ b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java @@ -92,9 +92,9 @@ public class DOOPRequestHandler implements DoipRequestHandler { DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder(); builder.createResponse(DoipResponseCode.Declined, msg); builder.setBody(bo.toByteArray()); - DoipMessage message = builder.create(); + builder.addAttributes("nodeID", String.valueOf(JavaScriptEntry.shardingID)); logger.error("buildRequestAndInvokeEngine has something wrong, executeWithoutLock err or validateJsonElementRulesByArgSchemaVisitor err"); - return message; + return builder.create(); } } diff --git a/src/main/java/org/bdware/sc/memory/MemoryDump.java b/src/main/java/org/bdware/sc/memory/MemoryDump.java index a9feed5..aabda2c 100644 --- a/src/main/java/org/bdware/sc/memory/MemoryDump.java +++ b/src/main/java/org/bdware/sc/memory/MemoryDump.java @@ -212,6 +212,7 @@ public class MemoryDump implements Serializable { break; case String: case Int: + case Boolean: obj = mo.data; break; case Double: