add joinCountFunc to functions saved to router and add DOOPAfterExecHandler

This commit is contained in:
haoeliu@foxmail.com 2023-02-18 19:47:07 +08:00
parent 29f81e582a
commit 098854fd46
6 changed files with 174 additions and 60 deletions

View File

@ -571,7 +571,8 @@ public class ContractProcess {
} }
if (fun.isDoipOperation()) { if (fun.isDoipOperation()) {
fun.appendBeforeInvokeHandler(DOOPHandler.createDOOPHandler()); fun.appendBeforeInvokeHandler(DOOPBeforeExecHandler.createDOOPHandler());
fun.appendAfterInvokeHandler(DOOPAfterExecHandler.createDOOPHandler());
} }
if (fun.isExport()) { if (fun.isExport()) {

View File

@ -2,7 +2,8 @@ package org.bdware.sc.compiler.ap;
import org.bdware.sc.bean.DoipOperationInfo; import org.bdware.sc.bean.DoipOperationInfo;
import org.bdware.sc.compiler.AnnotationProcessor; 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.handler.DOOPRequestHandler;
import org.bdware.sc.node.AnnotationNode; import org.bdware.sc.node.AnnotationNode;
import org.bdware.sc.node.ContractNode; import org.bdware.sc.node.ContractNode;
@ -25,8 +26,10 @@ public class DOOP extends AnnotationProcessor {
DOOPRequestHandler.instance.addDoipOperation(functionNode); DOOPRequestHandler.instance.addDoipOperation(functionNode);
// 维护DOOPHandler // 维护DOOPHandler
DOOPHandler.createDOOPHandler(); DOOPBeforeExecHandler.createDOOPHandler();
DOOPHandler.instance.putFuncNameAndDoipOperationsMapping(functionNode); DOOPBeforeExecHandler.instance.putFuncNameAndDoipOperationsMapping(functionNode);
DOOPAfterExecHandler.createDOOPHandler();
DOOPAfterExecHandler.instance.putFuncNameAndDoipOperationsMapping(functionNode);
// 维护ContractNodefunctionName is useless, use BasicOperation to map the corresponding functionNode // 维护ContractNodefunctionName is useless, use BasicOperation to map the corresponding functionNode
// contractNode.updateFunctionMap(functionNode.functionName, functionNode.getDoipOperationInfo().operationName); // contractNode.updateFunctionMap(functionNode.functionName, functionNode.getDoipOperationInfo().operationName);

View File

@ -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<String, BasicOperations> 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);
}
}
}

View File

@ -20,16 +20,16 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
public class DOOPHandler implements AnnotationHook { public class DOOPBeforeExecHandler implements AnnotationHook {
public static Map<String, BasicOperations> funcNameToDoipOperations; public static Map<String, BasicOperations> funcNameToDoipOperations;
public static DOOPHandler instance; public static DOOPBeforeExecHandler instance;
public DOOPHandler() { public DOOPBeforeExecHandler() {
funcNameToDoipOperations = new HashMap<>(); funcNameToDoipOperations = new HashMap<>();
} }
public static DOOPHandler createDOOPHandler() { public static DOOPBeforeExecHandler createDOOPHandler() {
if(instance == null) { if(instance == null) {
instance = new DOOPHandler(); instance = new DOOPBeforeExecHandler();
} }
return instance; 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) { public static DoipMessage convertHttpRequestToDoipMessage(ContractRequest httpReq) {
BasicOperations httpOperation = funcNameToDoipOperations.get(httpReq.getAction()); BasicOperations httpOperation = funcNameToDoipOperations.get(httpReq.getAction());
JsonObject jsonParams = JsonParser.parseString(httpReq.getArg().getAsString()).getAsJsonObject(); JsonObject jsonParams = JsonParser.parseString(httpReq.getArg().getAsString()).getAsJsonObject();
@ -185,36 +167,6 @@ public class DOOPHandler implements AnnotationHook {
return doipMessage; 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) { public static void validateJsonElementRulesByArgSchemaVisitor(JsonElement jsonElement, ArgSchemaVisitor visitor) {
visitor.visit(jsonElement); visitor.visit(jsonElement);

View File

@ -12,9 +12,10 @@ import org.bdware.doip.endpoint.server.NettyServerHandler;
import org.bdware.doip.endpoint.server.RepositoryHandler; import org.bdware.doip.endpoint.server.RepositoryHandler;
import org.bdware.sc.ContractProcess; import org.bdware.sc.ContractProcess;
import org.bdware.sc.bean.ContractRequest; 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.entity.DoipMessagePacker;
import org.bdware.sc.node.FunctionNode; import org.bdware.sc.node.FunctionNode;
import org.bdware.sc.util.JsonUtil;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -139,7 +140,7 @@ public class DOOPRequestHandler implements DoipRequestHandler, RepositoryHandler
try { try {
// 改变调用的函数 + 构造DoipMessagePacker // 改变调用的函数 + 构造DoipMessagePacker
Object ret = ContractProcess.instance.engine.executeWithoutLock(fn, contractRequest, arg); 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) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
logger.error("buildRequestAndInvokeEngine has something wrong, executeWithoutLock err or validateJsonElementRulesByArgSchemaVisitor err"); logger.error("buildRequestAndInvokeEngine has something wrong, executeWithoutLock err or validateJsonElementRulesByArgSchemaVisitor err");

View File

@ -147,12 +147,18 @@ public class DoipClusterServer extends DoipServerImpl {
// 对于JoinInfo进行维护 // 对于JoinInfo进行维护
if(doipFunctionJoinInfo != null) { if(doipFunctionJoinInfo != null) {
// 建立method和RouteInfo的映射 // 建立method和JoinInfo的映射
methodJoinInfoMap.addProperty(doipOperationName, gson.toJson(doipFunctionJoinInfo)); methodJoinInfoMap.addProperty(doipOperationName, gson.toJson(doipFunctionJoinInfo));
// 包装JoinInfo中用到的JoinFunction
if(doipFunctionJoinInfo.joinFuncName != null) { if(doipFunctionJoinInfo.joinFuncName != null) {
String joinFunctionName = doipFunctionJoinInfo.joinFuncName; String joinFunctionName = doipFunctionJoinInfo.joinFuncName;
packSourceFunctionAndDependentFunctions(allFunctions, joinFunctionName, functions); packSourceFunctionAndDependentFunctions(allFunctions, joinFunctionName, functions);
} }
// 包装JoinInfo中用到的JoinCountFunction
if(doipFunctionJoinInfo.joinCountFuncName != null) {
String joinFunctionCountName = doipFunctionJoinInfo.joinCountFuncName;
packSourceFunctionAndDependentFunctions(allFunctions, joinFunctionCountName, functions);
}
} }
} }
} }