From 098854fd46eda34a9741887ca71b26b30b8757cf Mon Sep 17 00:00:00 2001 From: "haoeliu@foxmail.com" Date: Sat, 18 Feb 2023 19:47:07 +0800 Subject: [PATCH] add joinCountFunc to functions saved to router and add DOOPAfterExecHandler --- .../java/org/bdware/sc/ContractProcess.java | 3 +- .../java/org/bdware/sc/compiler/ap/DOOP.java | 9 +- .../sc/engine/hook/DOOPAfterExecHandler.java | 151 ++++++++++++++++++ ...andler.java => DOOPBeforeExecHandler.java} | 58 +------ .../bdware/sc/handler/DOOPRequestHandler.java | 5 +- .../bdware/sc/server/DoipClusterServer.java | 8 +- 6 files changed, 174 insertions(+), 60 deletions(-) create mode 100644 src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java rename src/main/java/org/bdware/sc/engine/hook/{DOOPHandler.java => DOOPBeforeExecHandler.java} (78%) diff --git a/src/main/java/org/bdware/sc/ContractProcess.java b/src/main/java/org/bdware/sc/ContractProcess.java index 51be291..25159b6 100644 --- a/src/main/java/org/bdware/sc/ContractProcess.java +++ b/src/main/java/org/bdware/sc/ContractProcess.java @@ -571,7 +571,8 @@ public class ContractProcess { } if (fun.isDoipOperation()) { - fun.appendBeforeInvokeHandler(DOOPHandler.createDOOPHandler()); + fun.appendBeforeInvokeHandler(DOOPBeforeExecHandler.createDOOPHandler()); + fun.appendAfterInvokeHandler(DOOPAfterExecHandler.createDOOPHandler()); } if (fun.isExport()) { diff --git a/src/main/java/org/bdware/sc/compiler/ap/DOOP.java b/src/main/java/org/bdware/sc/compiler/ap/DOOP.java index 630c19a..4697fa6 100644 --- a/src/main/java/org/bdware/sc/compiler/ap/DOOP.java +++ b/src/main/java/org/bdware/sc/compiler/ap/DOOP.java @@ -2,7 +2,8 @@ package org.bdware.sc.compiler.ap; import org.bdware.sc.bean.DoipOperationInfo; import org.bdware.sc.compiler.AnnotationProcessor; -import org.bdware.sc.engine.hook.DOOPHandler; +import org.bdware.sc.engine.hook.DOOPAfterExecHandler; +import org.bdware.sc.engine.hook.DOOPBeforeExecHandler; import org.bdware.sc.handler.DOOPRequestHandler; import org.bdware.sc.node.AnnotationNode; import org.bdware.sc.node.ContractNode; @@ -25,8 +26,10 @@ public class DOOP extends AnnotationProcessor { DOOPRequestHandler.instance.addDoipOperation(functionNode); // 维护DOOPHandler - DOOPHandler.createDOOPHandler(); - DOOPHandler.instance.putFuncNameAndDoipOperationsMapping(functionNode); + DOOPBeforeExecHandler.createDOOPHandler(); + DOOPBeforeExecHandler.instance.putFuncNameAndDoipOperationsMapping(functionNode); + DOOPAfterExecHandler.createDOOPHandler(); + DOOPAfterExecHandler.instance.putFuncNameAndDoipOperationsMapping(functionNode); // 维护ContractNode,functionName is useless, use BasicOperation to map the corresponding functionNode // contractNode.updateFunctionMap(functionNode.functionName, functionNode.getDoipOperationInfo().operationName); diff --git a/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java b/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java new file mode 100644 index 0000000..3720657 --- /dev/null +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPAfterExecHandler.java @@ -0,0 +1,151 @@ +package org.bdware.sc.engine.hook; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.bdware.doip.codec.doipMessage.DoipMessage; +import org.bdware.doip.codec.doipMessage.DoipMessageFactory; +import org.bdware.doip.codec.doipMessage.DoipResponseCode; +import org.bdware.doip.codec.operations.BasicOperations; +import org.bdware.sc.JSEngine; +import org.bdware.sc.bean.ContractRequest; +import org.bdware.sc.boundry.ScriptReturnException; +import org.bdware.sc.entity.DoipMessagePacker; +import org.bdware.sc.node.AnnotationHook; +import org.bdware.sc.node.ArgPacks; +import org.bdware.sc.node.FunctionNode; +import org.bdware.sc.util.JsonUtil; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class DOOPAfterExecHandler implements AnnotationHook { + public static Map funcNameToDoipOperations; + public static DOOPAfterExecHandler instance; + public DOOPAfterExecHandler() { + funcNameToDoipOperations = new HashMap<>(); + } + + public static DOOPAfterExecHandler createDOOPHandler() { + if(instance == null) { + instance = new DOOPAfterExecHandler(); + } + + return instance; + } + + public void putFuncNameAndDoipOperationsMapping(FunctionNode fn) { + String basicOperationsString = fn.getDoipOperationInfo().operationType; + BasicOperations operation = BasicOperations.Unknown; + for(BasicOperations basicOperation : BasicOperations.values()) { + if(basicOperation.toString().equals(basicOperationsString)) { + operation = basicOperation; + } + } + funcNameToDoipOperations.put(fn.getFunctionName(), operation); + } + + @Override + public ArgPacks handle(JSEngine desktopEngine, ArgPacks argPacks) { + BasicOperations curOp = funcNameToDoipOperations.get(argPacks.request.getAction()); + Object originDoipMsgPacker = argPacks.arg; + DoipMessage originDoipMsg = null; + if (originDoipMsgPacker instanceof DoipMessagePacker) { + originDoipMsg = ((DoipMessagePacker) originDoipMsgPacker).rawDoipMsg; + } + + JsonElement jsonElementRes = JsonUtil.fromJson(JsonUtil.toJson(argPacks.ret), JsonElement.class); + JsonObject jsonObjectRes = JsonUtil.fromJson(JsonUtil.toJson(argPacks.ret), JsonObject.class); + + // validate json response + JsonElement jsonResponseRules = getRulesForJsonResponse(curOp); + ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonElementRes); + validateJsonElementRulesByArgSchemaVisitor(jsonResponseRules, visitor); + + JsonObject header = jsonObjectRes.get("header") != null ? jsonObjectRes.get("header").getAsJsonObject() : null; + String body = jsonObjectRes.get("body") != null ? jsonObjectRes.get("body").getAsString() : null; + + if(header != null) { + String headerRespCode = header.get("response") != null ? header.get("response").getAsString() : null; + if(headerRespCode != null) { + for (DoipResponseCode responseCode : DoipResponseCode.values()) { + if(responseCode.toString().equals(headerRespCode)) { + originDoipMsg.header.parameters.response = responseCode; + break; + } + } + } + } + + if(body != null) { + originDoipMsg.body.encodedData = body.getBytes(StandardCharsets.UTF_8); + } + + argPacks.ret = originDoipMsg; + return argPacks; + } + + + + public static JsonElement getRulesForJsonResponse(BasicOperations basicOperations) { + switch (basicOperations) { + case Hello: + case Retrieve: + case Create: + case Update: + case Search: + case ListOps: + return JsonParser.parseString("{\"!header\":{\"!response\":\"string\"}, \"!body\":\"string\"}"); + case Delete: + return JsonParser.parseString("{\"!header\":{\"!response\":\"string\"}, \"body\":\"string\"}"); + case Extension: + case Unknown: + default: + return null; + } + } + + // old convert jsonResponse from argPack's ret to Doip response in doip chain logic + public static DoipMessage convertJsonResponseToDoipMessage(FunctionNode fn, JsonElement jsonResponse, DoipMessage msg) { + BasicOperations curOp = funcNameToDoipOperations.get(fn.getFunctionName()); + JsonObject jsonParams = jsonResponse.getAsJsonObject(); + + // validate json response + JsonElement jsonResponseRules = getRulesForJsonResponse(curOp); + ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonResponse); + validateJsonElementRulesByArgSchemaVisitor(jsonResponseRules, visitor); + + JsonObject header = jsonParams.get("header") != null ? jsonParams.get("header").getAsJsonObject() : null; + String body = jsonParams.get("body") != null ? jsonParams.get("body").getAsString() : null; + + if(header != null) { + String headerRespCode = header.get("response") != null ? header.get("response").getAsString() : null; + if(headerRespCode != null) { + for (DoipResponseCode responseCode : DoipResponseCode.values()) { + if(responseCode.toString().equals(headerRespCode)) { + msg.header.parameters.response = responseCode; + break; + } + } + } + } + + if(body != null) { + msg.body.encodedData = body.getBytes(StandardCharsets.UTF_8); + } + + return msg; + } + + public static void validateJsonElementRulesByArgSchemaVisitor(JsonElement jsonElement, ArgSchemaVisitor visitor) { + visitor.visit(jsonElement); + if (!visitor.getStatus()) { + JsonObject jo = new JsonObject(); + jo.addProperty("msg", visitor.getException()); + jo.addProperty("code", visitor.errorCode); + throw new ScriptReturnException(jo); + } + } +} diff --git a/src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java b/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java similarity index 78% rename from src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java rename to src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java index bbed912..ee49665 100644 --- a/src/main/java/org/bdware/sc/engine/hook/DOOPHandler.java +++ b/src/main/java/org/bdware/sc/engine/hook/DOOPBeforeExecHandler.java @@ -20,16 +20,16 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -public class DOOPHandler implements AnnotationHook { +public class DOOPBeforeExecHandler implements AnnotationHook { public static Map funcNameToDoipOperations; - public static DOOPHandler instance; - public DOOPHandler() { + public static DOOPBeforeExecHandler instance; + public DOOPBeforeExecHandler() { funcNameToDoipOperations = new HashMap<>(); } - public static DOOPHandler createDOOPHandler() { + public static DOOPBeforeExecHandler createDOOPHandler() { if(instance == null) { - instance = new DOOPHandler(); + instance = new DOOPBeforeExecHandler(); } return instance; @@ -98,24 +98,6 @@ public class DOOPHandler implements AnnotationHook { } } - public static JsonElement getRulesForJsonResponse(BasicOperations basicOperations) { - switch (basicOperations) { - case Hello: - case Retrieve: - case Create: - case Update: - case Search: - case ListOps: - return JsonParser.parseString("{\"!header\":{\"!response\":\"string\"}, \"!body\":\"string\"}"); - case Delete: - return JsonParser.parseString("{\"!header\":{\"!response\":\"string\"}, \"body\":\"string\"}"); - case Extension: - case Unknown: - default: - return null; - } - } - public static DoipMessage convertHttpRequestToDoipMessage(ContractRequest httpReq) { BasicOperations httpOperation = funcNameToDoipOperations.get(httpReq.getAction()); JsonObject jsonParams = JsonParser.parseString(httpReq.getArg().getAsString()).getAsJsonObject(); @@ -185,36 +167,6 @@ public class DOOPHandler implements AnnotationHook { return doipMessage; } - public static DoipMessage convertJsonResponseToDoipMessage(FunctionNode fn, JsonElement jsonResponse, DoipMessage msg) { - BasicOperations curOp = funcNameToDoipOperations.get(fn.getFunctionName()); - JsonObject jsonParams = jsonResponse.getAsJsonObject(); - - // validate json response - JsonElement jsonResponseRules = getRulesForJsonResponse(curOp); - ArgSchemaVisitor visitor = new ArgSchemaVisitor(jsonResponse); - validateJsonElementRulesByArgSchemaVisitor(jsonResponseRules, visitor); - - JsonObject header = jsonParams.get("header") != null ? jsonParams.get("header").getAsJsonObject() : null; - String body = jsonParams.get("body") != null ? jsonParams.get("body").getAsString() : null; - - if(header != null) { - String headerRespCode = header.get("response") != null ? header.get("response").getAsString() : null; - if(headerRespCode != null) { - for (DoipResponseCode responseCode : DoipResponseCode.values()) { - if(responseCode.toString().equals(headerRespCode)) { - msg.header.parameters.response = responseCode; - break; - } - } - } - } - - if(body != null) { - msg.body.encodedData = body.getBytes(StandardCharsets.UTF_8); - } - - return msg; - } public static void validateJsonElementRulesByArgSchemaVisitor(JsonElement jsonElement, ArgSchemaVisitor visitor) { visitor.visit(jsonElement); diff --git a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java index c0c1c38..ed734d4 100644 --- a/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java +++ b/src/main/java/org/bdware/sc/handler/DOOPRequestHandler.java @@ -12,9 +12,10 @@ import org.bdware.doip.endpoint.server.NettyServerHandler; import org.bdware.doip.endpoint.server.RepositoryHandler; import org.bdware.sc.ContractProcess; import org.bdware.sc.bean.ContractRequest; -import org.bdware.sc.engine.hook.DOOPHandler; +import org.bdware.sc.engine.hook.DOOPBeforeExecHandler; import org.bdware.sc.entity.DoipMessagePacker; import org.bdware.sc.node.FunctionNode; +import org.bdware.sc.util.JsonUtil; import java.util.HashMap; import java.util.Map; @@ -139,7 +140,7 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler try { // 改变调用的函数 + 构造DoipMessagePacker Object ret = ContractProcess.instance.engine.executeWithoutLock(fn, contractRequest, arg); - return DOOPHandler.convertJsonResponseToDoipMessage(fn, (JsonElement) ret, msg); + return JsonUtil.fromJson(JsonUtil.toJson(ret), DoipMessage.class); } catch (Exception e) { e.printStackTrace(); logger.error("buildRequestAndInvokeEngine has something wrong, executeWithoutLock err or validateJsonElementRulesByArgSchemaVisitor err"); diff --git a/src/main/java/org/bdware/sc/server/DoipClusterServer.java b/src/main/java/org/bdware/sc/server/DoipClusterServer.java index b1560c2..e375c57 100644 --- a/src/main/java/org/bdware/sc/server/DoipClusterServer.java +++ b/src/main/java/org/bdware/sc/server/DoipClusterServer.java @@ -147,12 +147,18 @@ public class DoipClusterServer extends DoipServerImpl { // 对于JoinInfo进行维护 if(doipFunctionJoinInfo != null) { - // 建立method和RouteInfo的映射 + // 建立method和JoinInfo的映射 methodJoinInfoMap.addProperty(doipOperationName, gson.toJson(doipFunctionJoinInfo)); + // 包装JoinInfo中用到的JoinFunction if(doipFunctionJoinInfo.joinFuncName != null) { String joinFunctionName = doipFunctionJoinInfo.joinFuncName; packSourceFunctionAndDependentFunctions(allFunctions, joinFunctionName, functions); } + // 包装JoinInfo中用到的JoinCountFunction + if(doipFunctionJoinInfo.joinCountFuncName != null) { + String joinFunctionCountName = doipFunctionJoinInfo.joinCountFuncName; + packSourceFunctionAndDependentFunctions(allFunctions, joinFunctionCountName, functions); + } } } }